summaryrefslogtreecommitdiff
path: root/services/strategy-engine/tests/test_engine.py
diff options
context:
space:
mode:
Diffstat (limited to 'services/strategy-engine/tests/test_engine.py')
-rw-r--r--services/strategy-engine/tests/test_engine.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/services/strategy-engine/tests/test_engine.py b/services/strategy-engine/tests/test_engine.py
new file mode 100644
index 0000000..33ad4dd
--- /dev/null
+++ b/services/strategy-engine/tests/test_engine.py
@@ -0,0 +1,72 @@
+"""Tests for the StrategyEngine."""
+from datetime import datetime, timezone
+from decimal import Decimal
+from unittest.mock import AsyncMock, MagicMock
+
+import pytest
+
+from shared.models import Candle, Signal, OrderSide
+from shared.events import CandleEvent, SignalEvent
+from strategy_engine.engine import StrategyEngine
+
+
+def make_candle_event() -> dict:
+ candle = Candle(
+ symbol="BTC/USDT",
+ timeframe="1m",
+ open_time=datetime(2024, 1, 1, tzinfo=timezone.utc),
+ open=Decimal("50000"),
+ high=Decimal("50100"),
+ low=Decimal("49900"),
+ close=Decimal("50050"),
+ volume=Decimal("10.0"),
+ )
+ return CandleEvent(data=candle).to_dict()
+
+
+def make_signal() -> Signal:
+ return Signal(
+ strategy="test",
+ symbol="BTC/USDT",
+ side=OrderSide.BUY,
+ price=Decimal("50050"),
+ quantity=Decimal("0.01"),
+ reason="test signal",
+ )
+
+
+@pytest.mark.asyncio
+async def test_engine_dispatches_candle_to_strategies():
+ broker = MagicMock()
+ broker.read = AsyncMock(return_value=[make_candle_event()])
+ broker.publish = AsyncMock()
+
+ strategy = MagicMock()
+ strategy.on_candle = MagicMock(return_value=None)
+
+ engine = StrategyEngine(broker=broker, strategies=[strategy])
+ await engine.process_once("candles.BTC_USDT", "0")
+
+ strategy.on_candle.assert_called_once()
+ candle_arg = strategy.on_candle.call_args[0][0]
+ assert isinstance(candle_arg, Candle)
+ assert candle_arg.symbol == "BTC/USDT"
+
+
+@pytest.mark.asyncio
+async def test_engine_publishes_signal_when_strategy_returns_one():
+ broker = MagicMock()
+ broker.read = AsyncMock(return_value=[make_candle_event()])
+ broker.publish = AsyncMock()
+
+ strategy = MagicMock()
+ strategy.on_candle = MagicMock(return_value=make_signal())
+
+ engine = StrategyEngine(broker=broker, strategies=[strategy])
+ await engine.process_once("candles.BTC_USDT", "0")
+
+ broker.publish.assert_called_once()
+ call_args = broker.publish.call_args
+ assert call_args[0][0] == "signals"
+ published_data = call_args[0][1]
+ assert published_data["type"] == "SIGNAL"