"""Tests for strategy grouping module.""" import pytest from src.autopilot.strategy_groups import ( StrategyGroup, STRATEGY_TO_GROUP, GROUP_TO_STRATEGIES, get_strategy_group, get_strategies_in_group, get_all_groups, get_best_strategy_in_group, convert_strategy_to_group_label, ) class TestStrategyGroupMappings: """Tests for strategy group mappings.""" def test_all_strategies_have_group(self): """Verify all registered strategies are mapped to a group.""" # These are the strategies registered in src/strategies/__init__.py expected_strategies = [ "rsi", "macd", "moving_average", "confirmed", "divergence", "bollinger_mean_reversion", "dca", "grid", "momentum", "consensus", "pairs_trading", "volatility_breakout", "sentiment", "market_making" ] for strategy in expected_strategies: group = get_strategy_group(strategy) assert group is not None, f"Strategy '{strategy}' is not mapped to any group" def test_get_strategy_group_case_insensitive(self): """Test that strategy lookup is case-insensitive.""" assert get_strategy_group("RSI") == get_strategy_group("rsi") assert get_strategy_group("MACD") == get_strategy_group("macd") assert get_strategy_group("Moving_Average") == get_strategy_group("moving_average") def test_get_strategy_group_unknown(self): """Test that unknown strategies return None.""" assert get_strategy_group("nonexistent_strategy") is None assert get_strategy_group("") is None def test_group_to_strategies_reverse_mapping(self): """Verify GROUP_TO_STRATEGIES is the reverse of STRATEGY_TO_GROUP.""" for strategy, group in STRATEGY_TO_GROUP.items(): assert strategy in GROUP_TO_STRATEGIES[group] def test_all_groups_have_strategies(self): """Verify all groups have at least one strategy.""" for group in StrategyGroup: strategies = get_strategies_in_group(group) assert len(strategies) > 0, f"Group '{group}' has no strategies" class TestGetAllGroups: """Tests for get_all_groups function.""" def test_returns_all_groups(self): """Verify all groups are returned.""" groups = get_all_groups() assert len(groups) == 5 assert StrategyGroup.TREND_FOLLOWING in groups assert StrategyGroup.MEAN_REVERSION in groups assert StrategyGroup.MOMENTUM in groups assert StrategyGroup.MARKET_MAKING in groups assert StrategyGroup.SENTIMENT_BASED in groups class TestGetStrategiesInGroup: """Tests for get_strategies_in_group function.""" def test_trend_following_strategies(self): """Test trend following group contains expected strategies.""" strategies = get_strategies_in_group(StrategyGroup.TREND_FOLLOWING) assert "moving_average" in strategies assert "macd" in strategies assert "confirmed" in strategies def test_mean_reversion_strategies(self): """Test mean reversion group contains expected strategies.""" strategies = get_strategies_in_group(StrategyGroup.MEAN_REVERSION) assert "rsi" in strategies assert "bollinger_mean_reversion" in strategies assert "grid" in strategies def test_momentum_strategies(self): """Test momentum group contains expected strategies.""" strategies = get_strategies_in_group(StrategyGroup.MOMENTUM) assert "momentum" in strategies assert "volatility_breakout" in strategies class TestGetBestStrategyInGroup: """Tests for get_best_strategy_in_group function.""" def test_trend_following_high_adx(self): """Test trend following selection with high ADX.""" features = {"adx": 35.0, "rsi": 50.0, "atr_percent": 2.0, "volume_ratio": 1.0} strategy, confidence = get_best_strategy_in_group( StrategyGroup.TREND_FOLLOWING, features ) assert strategy == "confirmed" assert confidence > 0.5 def test_mean_reversion_extreme_rsi(self): """Test mean reversion selection with extreme RSI.""" features = {"adx": 15.0, "rsi": 25.0, "atr_percent": 1.5, "volume_ratio": 1.0} strategy, confidence = get_best_strategy_in_group( StrategyGroup.MEAN_REVERSION, features ) assert strategy == "rsi" assert confidence > 0.5 def test_momentum_high_volume(self): """Test momentum selection with high volume.""" features = {"adx": 25.0, "rsi": 55.0, "atr_percent": 3.0, "volume_ratio": 2.0} strategy, confidence = get_best_strategy_in_group( StrategyGroup.MOMENTUM, features ) assert strategy == "volatility_breakout" assert confidence > 0.5 def test_respects_available_strategies(self): """Test that only available strategies are selected.""" features = {"adx": 35.0, "rsi": 50.0} # Only MACD available from trend following strategy, confidence = get_best_strategy_in_group( StrategyGroup.TREND_FOLLOWING, features, available_strategies=["macd"] ) assert strategy == "macd" def test_fallback_when_no_strategies_available(self): """Test fallback when no strategies in group are available.""" features = {"adx": 25.0, "rsi": 50.0} strategy, confidence = get_best_strategy_in_group( StrategyGroup.TREND_FOLLOWING, features, available_strategies=["some_other_strategy"] ) # Should return safe default assert strategy == "rsi" assert confidence == 0.5 class TestConvertStrategyToGroupLabel: """Tests for convert_strategy_to_group_label function.""" def test_converts_known_strategies(self): """Test conversion of known strategies.""" assert convert_strategy_to_group_label("rsi") == "mean_reversion" assert convert_strategy_to_group_label("macd") == "trend_following" assert convert_strategy_to_group_label("momentum") == "momentum" assert convert_strategy_to_group_label("dca") == "market_making" assert convert_strategy_to_group_label("sentiment") == "sentiment_based" def test_unknown_strategy_returns_original(self): """Test that unknown strategies return original name.""" assert convert_strategy_to_group_label("unknown") == "unknown"