"""Test all 4 core scorers.""" import pytest from datetime import date class TestPriceStructureScorer: def test_computes_score(self, db_path): from scoring.price_structure import PriceStructureScorer scorer = PriceStructureScorer() result = scorer.compute(date(2026, 3, 15)) assert result.name == "Price Structure" assert 0 <= result.score <= 100 assert result.trend_strength >= 0 assert result.volatility_compression >= 0 assert result.momentum >= 0 assert result.label def test_bullish_in_trend(self, db_path): from scoring.price_structure import PriceStructureScorer scorer = PriceStructureScorer() result = scorer.compute(date(2025, 11, 15)) # TREND period assert result.score > 50 # Should be bullish in uptrend def test_bearish_in_panic(self, db_path): from scoring.price_structure import PriceStructureScorer scorer = PriceStructureScorer() result = scorer.compute(date(2026, 5, 15)) # PANIC period # In panic period, EMA alignment should be bearish assert result.trend_strength < 60 def test_no_data_handling(self, db_path): from scoring.price_structure import PriceStructureScorer scorer = PriceStructureScorer() result = scorer.compute(date(2020, 1, 1)) assert result.score == 50.0 assert result.label == "No Data" class TestBreadthScorer: def test_computes_score(self, db_path): from scoring.breadth_scorer import BreadthScorer scorer = BreadthScorer() result = scorer.compute(date(2026, 3, 15)) assert result.name == "Breadth" assert 0 <= result.score <= 100 assert result.breadth_bucket assert result.breadth_top20 >= 0 assert result.breadth_top50 >= 0 def test_tier_values(self, db_path): from scoring.breadth_scorer import BreadthScorer scorer = BreadthScorer() result = scorer.compute(date(2025, 11, 15)) # TREND period # Top20 should generally be higher than Top50 (large caps lead) assert result.breadth_top20 >= 0 assert result.breadth_top50 >= 0 def test_bucket_assignment(self, db_path): from scoring.breadth_scorer import BreadthScorer, BreadthBucket scorer = BreadthScorer() result = scorer.compute(date(2025, 11, 15)) # TREND: adv=42/50 assert result.breadth_bucket in ( BreadthBucket.EXTREME, BreadthBucket.STRONG, BreadthBucket.NORMAL ) def test_no_data(self, db_path): from scoring.breadth_scorer import BreadthScorer scorer = BreadthScorer() result = scorer.compute(date(2020, 1, 1)) assert result.score == 50.0 class TestOIMatrixScorer: def test_computes_state(self, db_path): from scoring.oi_matrix import OIMatrixScorer, OIState scorer = OIMatrixScorer() result = scorer.compute(date(2025, 11, 15)) # TREND period, oi_chg=+3.5 assert result.oi_state in OIState assert 0 <= result.score <= 100 def test_new_longs_in_trend(self, db_path): from scoring.oi_matrix import OIMatrixScorer, OIState scorer = OIMatrixScorer() # Test multiple dates in TREND period — at least one should be NEW_LONGS or NEUTRAL found_bullish = False for d in ["2025-11-15", "2025-11-20", "2025-12-01", "2025-12-15"]: result = scorer.compute(date.fromisoformat(d)) if result.oi_state in (OIState.NEW_LONGS, OIState.SHORT_COVERING, OIState.NEUTRAL): found_bullish = True break assert found_bullish, "No bullish OI state found in TREND period" def test_no_data(self, db_path): from scoring.oi_matrix import OIMatrixScorer scorer = OIMatrixScorer() result = scorer.compute(date(2020, 1, 1)) assert result.score == 50.0 assert result.label == "No Data" class TestVolatilityRegimeScorer: def test_computes_regime(self, db_path): from scoring.volatility_regime import VolatilityRegimeScorer, VolRegime scorer = VolatilityRegimeScorer() result = scorer.compute(date(2026, 3, 15)) assert result.vol_regime in VolRegime assert 0 <= result.score <= 100 def test_higher_vol_in_panic(self, db_path): from scoring.volatility_regime import VolatilityRegimeScorer, VolRegime scorer = VolatilityRegimeScorer() trend_result = scorer.compute(date(2025, 11, 15)) panic_result = scorer.compute(date(2026, 5, 15)) # PANIC period has higher ATR → higher vol regime or score assert panic_result.atr_pct >= trend_result.atr_pct * 0.5 # at least comparable def test_no_data(self, db_path): from scoring.volatility_regime import VolatilityRegimeScorer scorer = VolatilityRegimeScorer() result = scorer.compute(date(2020, 1, 1)) assert result.score == 50.0