diff --git a/tests/test_research_pipeline.py b/tests/test_research_pipeline.py index 0923d27..310e245 100644 --- a/tests/test_research_pipeline.py +++ b/tests/test_research_pipeline.py @@ -291,3 +291,46 @@ def test_factor_backtest_exposes_net_benchmark_metrics() -> None: assert relative["n_observations"] == len(result.returns) assert relative["tracking_error"] > 0 + + +def test_factor_backtest_projects_actual_close_weights_from_ledger() -> None: + dates = _calendar() + scores = pd.DataFrame({"A": [1.0], "B": [0.0]}, index=dates[:1]) + opens = pd.DataFrame( + {"A": [10.0, 10.0, 10.0, 10.0], "B": [20.0, 20.0, 20.0, 20.0]}, + index=dates, + ) + closes = pd.DataFrame( + {"A": [10.0, 11.0, 12.0, 12.0], "B": [20.0, 20.0, 20.0, 20.0]}, + index=dates, + ) + result = run_factor_backtest_research( + scores, + opens, + closes, + top_k=1, + gross_exposure=0.5, + execution_price_field="open", + valuation_price_field="close", + initial_cash=1_000.0, + config=ExecutionConfig( + commission_bps=0, + stamp_tax_bps=0, + slippage_bps=0, + min_trade_amount=0, + ), + ) + + weights = result.position_weights + cash = result.cash_weights + + assert weights.index.equals(result.nav.index) + assert weights.columns.tolist() == ["A", "B"] + assert weights.loc[dates[0]].sum() == 0.0 + assert cash.loc[dates[0]] == 1.0 + assert weights.loc[dates[1], "A"] == pytest.approx(550.0 / 1_050.0) + pd.testing.assert_series_equal( + weights.sum(axis=1) + cash, + pd.Series(1.0, index=dates), + check_names=False, + )