summaryrefslogtreecommitdiff
path: root/services/strategy-engine/tests/test_combined_strategy.py
diff options
context:
space:
mode:
Diffstat (limited to 'services/strategy-engine/tests/test_combined_strategy.py')
-rw-r--r--services/strategy-engine/tests/test_combined_strategy.py70
1 files changed, 64 insertions, 6 deletions
diff --git a/services/strategy-engine/tests/test_combined_strategy.py b/services/strategy-engine/tests/test_combined_strategy.py
index 3408a89..6a15250 100644
--- a/services/strategy-engine/tests/test_combined_strategy.py
+++ b/services/strategy-engine/tests/test_combined_strategy.py
@@ -5,13 +5,14 @@ from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
+from datetime import UTC, datetime
from decimal import Decimal
-from datetime import datetime, timezone
-import pytest
-from shared.models import Candle, Signal, OrderSide
-from strategies.combined_strategy import CombinedStrategy
+import pytest
from strategies.base import BaseStrategy
+from strategies.combined_strategy import CombinedStrategy
+
+from shared.models import Candle, OrderSide, Signal
class AlwaysBuyStrategy(BaseStrategy):
@@ -72,9 +73,9 @@ class NeutralStrategy(BaseStrategy):
def _candle(price=100.0):
return Candle(
- symbol="BTCUSDT",
+ symbol="AAPL",
timeframe="1m",
- open_time=datetime(2025, 1, 1, tzinfo=timezone.utc),
+ open_time=datetime(2025, 1, 1, tzinfo=UTC),
open=Decimal(str(price)),
high=Decimal(str(price + 10)),
low=Decimal(str(price - 10)),
@@ -167,3 +168,60 @@ def test_combined_invalid_weight():
c.configure({})
with pytest.raises(ValueError):
c.add_strategy(AlwaysBuyStrategy(), weight=-1.0)
+
+
+def test_combined_record_result():
+ """Verify trade history tracking works correctly."""
+ c = CombinedStrategy()
+ c.configure({"adaptive_weights": True, "history_window": 5})
+
+ c.record_result("test_strat", True)
+ c.record_result("test_strat", False)
+ c.record_result("test_strat", True)
+
+ assert len(c._trade_history["test_strat"]) == 3
+ assert c._trade_history["test_strat"] == [True, False, True]
+
+ # Fill beyond window size to test trimming
+ for _ in range(5):
+ c.record_result("test_strat", False)
+
+ assert len(c._trade_history["test_strat"]) == 5 # Trimmed to history_window
+
+
+def test_combined_adaptive_weight_increases_for_winners():
+ """Strategy with high win rate gets higher effective weight."""
+ c = CombinedStrategy()
+ c.configure({"threshold": 0.3, "adaptive_weights": True, "history_window": 20})
+ c.add_strategy(AlwaysBuyStrategy(), weight=1.0)
+
+ # Record high win rate for always_buy (80% wins)
+ for _ in range(8):
+ c.record_result("always_buy", True)
+ for _ in range(2):
+ c.record_result("always_buy", False)
+
+ # Adaptive weight should be > base weight (1.0)
+ adaptive_w = c._get_adaptive_weight("always_buy", 1.0)
+ assert adaptive_w > 1.0
+ # 80% win rate -> scale = 0.5 + 0.8 = 1.3 -> weight = 1.3
+ assert abs(adaptive_w - 1.3) < 0.01
+
+
+def test_combined_adaptive_weight_decreases_for_losers():
+ """Strategy with low win rate gets lower effective weight."""
+ c = CombinedStrategy()
+ c.configure({"threshold": 0.3, "adaptive_weights": True, "history_window": 20})
+ c.add_strategy(AlwaysBuyStrategy(), weight=1.0)
+
+ # Record low win rate for always_buy (20% wins)
+ for _ in range(2):
+ c.record_result("always_buy", True)
+ for _ in range(8):
+ c.record_result("always_buy", False)
+
+ # Adaptive weight should be < base weight (1.0)
+ adaptive_w = c._get_adaptive_weight("always_buy", 1.0)
+ assert adaptive_w < 1.0
+ # 20% win rate -> scale = 0.5 + 0.2 = 0.7 -> weight = 0.7
+ assert abs(adaptive_w - 0.7) < 0.01