feat: include signal facts in research artifact
This commit is contained in:
@@ -51,6 +51,7 @@ class ResearchRunArtifact:
|
||||
|
||||
schema_version: str
|
||||
_run: pd.DataFrame
|
||||
_signals: pd.DataFrame
|
||||
_nav: pd.DataFrame
|
||||
_trades: pd.DataFrame
|
||||
_positions: pd.DataFrame
|
||||
@@ -67,6 +68,10 @@ class ResearchRunArtifact:
|
||||
def nav(self) -> pd.DataFrame:
|
||||
return _frame_copy(self._nav)
|
||||
|
||||
@property
|
||||
def signals(self) -> pd.DataFrame:
|
||||
return _frame_copy(self._signals)
|
||||
|
||||
@property
|
||||
def trades(self) -> pd.DataFrame:
|
||||
return _frame_copy(self._trades)
|
||||
@@ -95,6 +100,7 @@ class ResearchRunArtifact:
|
||||
"""Return isolated table snapshots keyed by stable logical table name."""
|
||||
return {
|
||||
"run": self.run,
|
||||
"signals": self.signals,
|
||||
"nav": self.nav,
|
||||
"trades": self.trades,
|
||||
"positions": self.positions,
|
||||
@@ -140,6 +146,7 @@ class ResearchRunArtifact:
|
||||
def _internal_table_frames(self) -> Mapping[str, pd.DataFrame]:
|
||||
return {
|
||||
"run": self._run,
|
||||
"signals": self._signals,
|
||||
"nav": self._nav,
|
||||
"trades": self._trades,
|
||||
"positions": self._positions,
|
||||
@@ -234,6 +241,34 @@ def _build_nav(
|
||||
return nav
|
||||
|
||||
|
||||
def _build_signals(result: FactorBacktestResult, run_id: str) -> pd.DataFrame:
|
||||
columns = [
|
||||
"run_id",
|
||||
"signal_date",
|
||||
"execution_date",
|
||||
"asset_id",
|
||||
"factor_score",
|
||||
"target_weight",
|
||||
]
|
||||
rows: list[dict[str, object]] = []
|
||||
for signal_date, scores in result.factor_scores.iterrows():
|
||||
execution_date = pd.Timestamp(result.schedule.signal_to_execution.at[signal_date]).date()
|
||||
for asset, score in scores.items():
|
||||
rows.append(
|
||||
{
|
||||
"run_id": run_id,
|
||||
"signal_date": pd.Timestamp(signal_date).date(),
|
||||
"execution_date": execution_date,
|
||||
"asset_id": asset,
|
||||
"factor_score": float(score),
|
||||
"target_weight": float(
|
||||
result.schedule.decision_weights.at[signal_date, asset]
|
||||
),
|
||||
}
|
||||
)
|
||||
return pd.DataFrame(rows, columns=columns)
|
||||
|
||||
|
||||
def _build_trades(result: FactorBacktestResult, run_id: str) -> pd.DataFrame:
|
||||
trades = result.execution.trades_frame.copy(deep=True)
|
||||
trades.insert(0, "run_id", run_id)
|
||||
@@ -445,6 +480,7 @@ def build_research_run_artifact(
|
||||
return ResearchRunArtifact(
|
||||
schema_version=RESEARCH_ARTIFACT_SCHEMA_VERSION,
|
||||
_run=run,
|
||||
_signals=_build_signals(result, normalized_run_id),
|
||||
_nav=_build_nav(result, normalized_run_id, benchmark_returns),
|
||||
_trades=_build_trades(result, normalized_run_id),
|
||||
_positions=_build_positions(result, normalized_run_id),
|
||||
|
||||
Reference in New Issue
Block a user