"""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 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"