1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
"""Test that strategy engine processes multiple symbols concurrently."""
import sys
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock
import pytest
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from datetime import UTC, datetime
from decimal import Decimal
from strategy_engine.engine import StrategyEngine
from shared.events import CandleEvent
from shared.models import Candle
@pytest.mark.asyncio
async def test_engine_processes_multiple_streams():
"""Verify engine can process candles from different streams."""
broker = AsyncMock()
candle_btc = Candle(
symbol="AAPL",
timeframe="1m",
open_time=datetime(2025, 1, 1, tzinfo=UTC),
open=Decimal("50000"),
high=Decimal("51000"),
low=Decimal("49000"),
close=Decimal("50000"),
volume=Decimal("10"),
)
candle_eth = Candle(
symbol="MSFT",
timeframe="1m",
open_time=datetime(2025, 1, 1, tzinfo=UTC),
open=Decimal("3000"),
high=Decimal("3100"),
low=Decimal("2900"),
close=Decimal("3000"),
volume=Decimal("10"),
)
btc_events = [CandleEvent(data=candle_btc).to_dict()]
eth_events = [CandleEvent(data=candle_eth).to_dict()]
# First call returns AAPL event, second MSFT, then empty
call_count = {"aapl": 0, "msft": 0}
async def mock_read(stream, **kwargs):
if "AAPL" in stream:
call_count["aapl"] += 1
return btc_events if call_count["aapl"] == 1 else []
elif "MSFT" in stream:
call_count["msft"] += 1
return eth_events if call_count["msft"] == 1 else []
return []
broker.read = AsyncMock(side_effect=mock_read)
strategy = MagicMock()
strategy.on_candle = MagicMock(return_value=None)
engine = StrategyEngine(broker=broker, strategies=[strategy])
# Process both streams
await engine.process_once("candles.AAPL", "$")
await engine.process_once("candles.MSFT", "$")
# Strategy should have been called with both candles
assert strategy.on_candle.call_count == 2
|