"""Tests for the StrategyEngine.""" from datetime import UTC, datetime from decimal import Decimal from unittest.mock import AsyncMock, MagicMock import pytest from strategy_engine.engine import StrategyEngine from shared.events import CandleEvent from shared.models import Candle, OrderSide, Signal def make_candle_event() -> dict: candle = Candle( symbol="AAPL", timeframe="1m", open_time=datetime(2024, 1, 1, tzinfo=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="AAPL", 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.AAPL", "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 == "AAPL" @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.AAPL", "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"