import unittest import warnings import numpy as np import pandas as pd class AlphaSignalTests(unittest.TestCase): def test_build_regime_filter_requires_market_trend_and_non_market_leader(self): from research.regime_filters import build_regime_filter dates = pd.date_range("2023-01-01", periods=260, freq="D") spy = pd.Series([100.0 + i for i in range(260)], index=dates) qqq_leader = pd.Series([100.0 + 1.4 * i for i in range(260)], index=dates) xlu = pd.Series([100.0 + 0.2 * i for i in range(260)], index=dates) with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") bullish = build_regime_filter(pd.DataFrame({"SPY": spy, "QQQ": qqq_leader, "XLU": xlu})) qqq_laggard = pd.Series([100.0 + 0.5 * i for i in range(260)], index=dates) no_leader = build_regime_filter(pd.DataFrame({"SPY": spy, "QQQ": qqq_laggard, "XLU": xlu})) self.assertEqual(len(caught), 0) self.assertFalse(bool(bullish.iloc[199])) self.assertTrue(bool(bullish.iloc[-1])) self.assertFalse(bool(no_leader.iloc[-1])) def test_build_regime_filter_handles_internal_missing_prices_without_warnings(self): from research.regime_filters import build_regime_filter dates = pd.date_range("2023-01-01", periods=260, freq="D") spy = pd.Series([100.0 + i for i in range(260)], index=dates) qqq = pd.Series([100.0 + 1.4 * i for i in range(260)], index=dates) qqq.iloc[120] = np.nan etf_close = pd.DataFrame({"SPY": spy, "QQQ": qqq, "XLU": 100.0}, index=dates) with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") regime = build_regime_filter(etf_close) self.assertEqual(len(caught), 0) self.assertEqual(str(regime.dtype), "bool") def test_breakout_after_compression_score_is_shifted_and_rewards_breakout_profile(self): from research.event_factors import breakout_after_compression_score dates = pd.date_range("2024-01-01", periods=80, freq="D") aaa_close = [100.0 + i for i in range(60)] + [159.0 + 0.05 * i for i in range(20)] bbb_close = [100.0 + i for i in range(60)] + [150.0 - i for i in range(20)] close = pd.DataFrame({"AAA": aaa_close, "BBB": bbb_close}, index=dates) high = pd.DataFrame( { "AAA": [value + 0.4 for value in aaa_close], "BBB": [value + 4.0 for value in bbb_close], }, index=dates, ) low = pd.DataFrame( { "AAA": [value - 0.4 for value in aaa_close], "BBB": [value - 4.0 for value in bbb_close], }, index=dates, ) volume = pd.DataFrame( { "AAA": [1_000.0] * 79 + [1_000.0], "BBB": [1_000.0] * 80, }, index=dates, ) volume.loc[dates[-2], "AAA"] = 6_000.0 shifted_result = breakout_after_compression_score(close, high, low, volume) self.assertGreater( shifted_result.loc[dates[-1], "AAA"], shifted_result.loc[dates[-1], "BBB"], ) changed_last_day = close.copy() changed_last_day_high = high.copy() changed_last_day_low = low.copy() changed_last_day_volume = volume.copy() changed_last_day.loc[dates[-1], "AAA"] = 120.0 changed_last_day_high.loc[dates[-1], "AAA"] = 130.0 changed_last_day_low.loc[dates[-1], "AAA"] = 110.0 changed_last_day_volume.loc[dates[-1], "AAA"] = 20_000.0 last_day_changed_result = breakout_after_compression_score( changed_last_day, changed_last_day_high, changed_last_day_low, changed_last_day_volume, ) self.assertEqual( shifted_result.loc[dates[-1], "AAA"], last_day_changed_result.loc[dates[-1], "AAA"], ) def test_breakout_after_compression_score_keeps_float_output_when_denominators_hit_zero(self): from research.event_factors import breakout_after_compression_score dates = pd.date_range("2024-01-01", periods=70, freq="D") close = pd.DataFrame({"AAA": [10.0] * 70}, index=dates) high = pd.DataFrame({"AAA": [10.0] * 70}, index=dates) low = pd.DataFrame({"AAA": [10.0] * 70}, index=dates) volume = pd.DataFrame({"AAA": [0.0] * 70}, index=dates) score = breakout_after_compression_score(close, high, low, volume) self.assertEqual(str(score.dtypes["AAA"]), "float64") self.assertTrue(pd.isna(score.iloc[-1]["AAA"])) if __name__ == "__main__": unittest.main()