Compare commits

...
2 Commits
Author SHA1 Message Date
ao gong a3cefe364d feat: add deterministic trade and signal identity 2026-08-21 22:32:37 +08:00
ao gong d6c3614301 test: require deterministic trade identity 2026-08-21 22:32:14 +08:00
2 changed files with 16 additions and 0 deletions
+13
View File
@@ -273,6 +273,19 @@ 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)
trades["trade_date"] = pd.to_datetime(trades["trade_date"]).dt.date
trades.insert(
1,
"trade_id",
[f"{run_id}:{sequence:08d}" for sequence in range(1, len(trades) + 1)],
)
signal_by_execution = {
pd.Timestamp(execution_date).date(): pd.Timestamp(signal_date).date()
for signal_date, execution_date in result.schedule.signal_to_execution.items()
}
trades["signal_id"] = [
f"{run_id}:signal:{signal_by_execution[trade_date].isoformat()}"
for trade_date in trades["trade_date"]
]
trades["total_cost"] = trades["fee"] + trades["slippage"]
return trades
+3
View File
@@ -106,6 +106,9 @@ def test_research_artifact_projects_versioned_queryable_fact_tables() -> None:
result.schedule.signal_to_execution.iloc[0].date()
]
assert set(artifact.trades["side"]) == {"buy", "sell"}
assert artifact.trades["trade_id"].is_unique
assert artifact.trades["trade_id"].str.startswith("run-20260105-a:").all()
assert artifact.trades["signal_id"].str.startswith("run-20260105-a:signal:").all()
assert {"security", "cash"}.issubset(set(artifact.positions["asset_type"]))
assert artifact.positions.groupby("trade_date")["weight"].sum().tolist() == pytest.approx(
[1.0, 1.0, 1.0, 1.0]