Local changes: Updated model training, removed debug instrumentation, and configuration improvements

This commit is contained in:
kfox
2025-12-26 01:15:43 -05:00
commit cc60da49e7
388 changed files with 57127 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
"""Tests for autopilot module."""

View File

@@ -0,0 +1,175 @@
"""Tests for intelligent autopilot functionality."""
import pytest
from decimal import Decimal
from unittest.mock import Mock, patch, AsyncMock
from src.core.database import OrderSide, OrderType
class TestPreFlightValidation:
"""Tests for pre-flight order validation."""
@pytest.fixture
def mock_autopilot(self):
"""Create mock autopilot with necessary attributes."""
from src.autopilot.intelligent_autopilot import IntelligentAutopilot
with patch.object(IntelligentAutopilot, '__init__', lambda x, *args, **kwargs: None):
autopilot = IntelligentAutopilot.__new__(IntelligentAutopilot)
autopilot.symbol = 'BTC/USD'
autopilot.paper_trading = True
autopilot.logger = Mock()
# Mock trading engine
autopilot.trading_engine = Mock()
autopilot.trading_engine.paper_trading = Mock()
autopilot.trading_engine.paper_trading.get_balance.return_value = Decimal('1000.0')
autopilot.trading_engine.paper_trading.get_positions.return_value = []
return autopilot
@pytest.mark.asyncio
async def test_can_execute_order_insufficient_funds(self, mock_autopilot):
"""Test that insufficient funds returns False."""
mock_autopilot.trading_engine.paper_trading.get_balance.return_value = Decimal('10.0')
can_execute, reason = await mock_autopilot._can_execute_order(
side=OrderSide.BUY,
quantity=Decimal('1.0'),
price=Decimal('100.0')
)
assert can_execute is False
assert 'Insufficient funds' in reason
@pytest.mark.asyncio
async def test_can_execute_order_sufficient_funds(self, mock_autopilot):
"""Test that sufficient funds returns True."""
mock_autopilot.trading_engine.paper_trading.get_balance.return_value = Decimal('1000.0')
can_execute, reason = await mock_autopilot._can_execute_order(
side=OrderSide.BUY,
quantity=Decimal('1.0'),
price=Decimal('100.0')
)
assert can_execute is True
assert reason == 'OK'
@pytest.mark.asyncio
async def test_can_execute_order_no_position_for_sell(self, mock_autopilot):
"""Test that SELL without position returns False."""
mock_autopilot.trading_engine.paper_trading.get_positions.return_value = []
can_execute, reason = await mock_autopilot._can_execute_order(
side=OrderSide.SELL,
quantity=Decimal('1.0'),
price=Decimal('100.0')
)
assert can_execute is False
assert 'No position to sell' in reason
@pytest.mark.asyncio
async def test_can_execute_order_minimum_value(self, mock_autopilot):
"""Test that order below minimum value returns False."""
can_execute, reason = await mock_autopilot._can_execute_order(
side=OrderSide.BUY,
quantity=Decimal('0.001'),
price=Decimal('0.10') # Order value = $0.0001
)
assert can_execute is False
assert 'below minimum' in reason
class TestSmartOrderTypeSelection:
"""Tests for smart order type selection."""
@pytest.fixture
def mock_autopilot(self):
"""Create mock autopilot for order type tests."""
from src.autopilot.intelligent_autopilot import IntelligentAutopilot
with patch.object(IntelligentAutopilot, '__init__', lambda x, *args, **kwargs: None):
autopilot = IntelligentAutopilot.__new__(IntelligentAutopilot)
autopilot.logger = Mock()
return autopilot
def test_strong_signal_uses_market(self, mock_autopilot):
"""Test that strong signals (>80%) use MARKET orders."""
order_type, price = mock_autopilot._determine_order_type_and_price(
side=OrderSide.BUY,
signal_strength=0.85,
current_price=Decimal('100.0'),
is_stop_loss=False
)
assert order_type == OrderType.MARKET
assert price is None
def test_normal_signal_uses_limit(self, mock_autopilot):
"""Test that normal signals use LIMIT orders."""
order_type, price = mock_autopilot._determine_order_type_and_price(
side=OrderSide.BUY,
signal_strength=0.65,
current_price=Decimal('100.0'),
is_stop_loss=False
)
assert order_type == OrderType.LIMIT
assert price is not None
# BUY limit should be below market
assert price < Decimal('100.0')
def test_stop_loss_uses_market(self, mock_autopilot):
"""Test that stop-loss exits use MARKET orders."""
order_type, price = mock_autopilot._determine_order_type_and_price(
side=OrderSide.SELL,
signal_strength=0.5,
current_price=Decimal('100.0'),
is_stop_loss=True
)
assert order_type == OrderType.MARKET
assert price is None
def test_take_profit_uses_limit(self, mock_autopilot):
"""Test that take-profit exits can use LIMIT orders."""
order_type, price = mock_autopilot._determine_order_type_and_price(
side=OrderSide.SELL,
signal_strength=0.6,
current_price=Decimal('100.0'),
is_stop_loss=False
)
assert order_type == OrderType.LIMIT
assert price is not None
# SELL limit should be above market
assert price > Decimal('100.0')
def test_buy_limit_price_discount(self, mock_autopilot):
"""Test BUY LIMIT price is 0.1% below market."""
order_type, price = mock_autopilot._determine_order_type_and_price(
side=OrderSide.BUY,
signal_strength=0.6,
current_price=Decimal('1000.00'),
is_stop_loss=False
)
# 0.1% discount = 999.00
expected = Decimal('999.00')
assert price == expected
def test_sell_limit_price_premium(self, mock_autopilot):
"""Test SELL LIMIT price is 0.1% above market."""
order_type, price = mock_autopilot._determine_order_type_and_price(
side=OrderSide.SELL,
signal_strength=0.6,
current_price=Decimal('1000.00'),
is_stop_loss=False
)
# 0.1% premium = 1001.00
expected = Decimal('1001.00')
assert price == expected

View File

@@ -0,0 +1,161 @@
"""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"