diff --git a/tests/test_factor_attribution.py b/tests/test_factor_attribution.py index a259834..3437a76 100644 --- a/tests/test_factor_attribution.py +++ b/tests/test_factor_attribution.py @@ -316,6 +316,48 @@ class LocalFactorConstructionTests(unittest.TestCase): self.assertTrue(factors.iloc[260:].notna().all().all()) self.assertGreater(factors.iloc[260:].abs().sum().sum(), 0.0) + def test_build_extension_factors_does_not_use_future_prices(self): + prices = self._make_price_frame(benchmark="SPY") + mutated = prices.copy() + future_start = prices.index[280] + mutated.loc[future_start:, "A"] = mutated.loc[future_start:, "A"] * 1.8 + mutated.loc[future_start:, "B"] = mutated.loc[future_start:, "B"] * 0.4 + + original = build_extension_factors(prices, benchmark="SPY", market="us") + changed = build_extension_factors(mutated, benchmark="SPY", market="us") + + comparison_end = prices.index[279] + pd.testing.assert_frame_equal(original.loc[:comparison_end], changed.loc[:comparison_end]) + self.assertGreater( + (original.loc[future_start:] - changed.loc[future_start:]).abs().sum().sum(), + 0.0, + ) + + def test_build_proxy_core_factors_does_not_use_future_prices(self): + prices = self._make_price_frame(benchmark="000300.SS") + mutated = prices.copy() + future_start = prices.index[280] + mutated.loc[future_start:, "C"] = mutated.loc[future_start:, "C"] * 0.35 + mutated.loc[future_start:, "D"] = mutated.loc[future_start:, "D"] * 1.6 + + original = build_proxy_core_factors(prices, benchmark="000300.SS", market="cn") + changed = build_proxy_core_factors(mutated, benchmark="000300.SS", market="cn") + + comparison_end = prices.index[279] + pd.testing.assert_frame_equal(original.loc[:comparison_end], changed.loc[:comparison_end]) + self.assertGreater( + (original.loc[future_start:] - changed.loc[future_start:]).abs().sum().sum(), + 0.0, + ) + + def test_build_proxy_core_factors_falls_back_to_equal_weight_market_when_benchmark_missing(self): + prices = self._make_price_frame(benchmark="CN_BENCH").drop(columns=["CN_BENCH"]) + + factors = build_proxy_core_factors(prices, benchmark="000300.SS", market="cn") + + expected_market = prices.pct_change().mean(axis=1) + pd.testing.assert_series_equal(factors["MKT"], expected_market, check_names=False) + def _make_price_frame(self, benchmark: str) -> pd.DataFrame: dates = pd.date_range("2025-01-01", periods=320, freq="B") steps = np.arange(len(dates), dtype=float)