summaryrefslogtreecommitdiff
path: root/services/strategy-engine/tests/test_multi_symbol.py
blob: 922bfc2f4d2195f654520da7e973219943e902db (plain)
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