99 lines
3.2 KiB
Python
99 lines
3.2 KiB
Python
"""Tests for watch_ticker and watch_ohlcv (polling-based watching)."""
|
|
|
|
import asyncio
|
|
import time
|
|
|
|
import responses
|
|
import pytest
|
|
|
|
import mt5bridge_ccxt
|
|
|
|
|
|
class TestWatchTicker:
|
|
@responses.activate
|
|
def test_returns_immediately_when_changed(self, exchange_config, mock_ticker):
|
|
# Two different ticks to simulate change
|
|
responses.add(
|
|
responses.GET,
|
|
"http://mock-mt5bridge:8080/symbols/XAUUSDc/tick",
|
|
json=mock_ticker, status=200,
|
|
)
|
|
mock_ticker2 = dict(mock_ticker)
|
|
mock_ticker2["data"] = [dict(mock_ticker["data"][0])]
|
|
mock_ticker2["data"][0]["bid"] = 4181.0 # price changed
|
|
mock_ticker2["data"][0]["ask"] = 4181.5
|
|
responses.add(
|
|
responses.GET,
|
|
"http://mock-mt5bridge:8080/symbols/XAUUSDc/tick",
|
|
json=mock_ticker2, status=200,
|
|
)
|
|
|
|
ex = mt5bridge_ccxt.mt5bridge(exchange_config)
|
|
result = asyncio.run(
|
|
ex.watch_ticker("XAU/USD", params={"poll_interval_ms": 50})
|
|
)
|
|
assert result["symbol"] == "XAU/USD"
|
|
assert result["bid"] in (4180.5, 4181.0)
|
|
|
|
@responses.activate
|
|
def test_returns_after_max_wait_even_if_unchanged(self, exchange_config, mock_ticker):
|
|
# Same tick twice → no change
|
|
responses.add(
|
|
responses.GET,
|
|
"http://mock-mt5bridge:8080/symbols/XAUUSDc/tick",
|
|
json=mock_ticker, status=200,
|
|
)
|
|
responses.add(
|
|
responses.GET,
|
|
"http://mock-mt5bridge:8080/symbols/XAUUSDc/tick",
|
|
json=mock_ticker, status=200,
|
|
)
|
|
|
|
ex = mt5bridge_ccxt.mt5bridge(exchange_config)
|
|
start = time.time()
|
|
result = asyncio.run(
|
|
ex.watch_ticker(
|
|
"XAU/USD",
|
|
params={"poll_interval_ms": 50, "max_wait_ms": 200},
|
|
)
|
|
)
|
|
elapsed = time.time() - start
|
|
# Should return after ~200ms even though nothing changed
|
|
assert elapsed >= 0.2
|
|
assert elapsed < 1.0 # but not much more
|
|
assert result["bid"] == 4180.5
|
|
|
|
|
|
class TestWatchOHLCV:
|
|
@responses.activate
|
|
def test_returns_new_bar(self, exchange_config, mock_bars):
|
|
# Second call returns a new bar
|
|
mock_bars2 = {
|
|
"data": [
|
|
*mock_bars["data"],
|
|
{"time": "2026-07-08T13:00:00", "open": 4184.0, "high": 4188.0,
|
|
"low": 4183.0, "close": 4186.0, "tick_volume": 90, "spread": 5,
|
|
"real_volume": 45.0},
|
|
],
|
|
"count": 3, "format": "json",
|
|
}
|
|
responses.add(
|
|
responses.GET,
|
|
"http://mock-mt5bridge:8080/rates/from-pos",
|
|
json=mock_bars, status=200,
|
|
)
|
|
responses.add(
|
|
responses.GET,
|
|
"http://mock-mt5bridge:8080/rates/from-pos",
|
|
json=mock_bars2, status=200,
|
|
)
|
|
|
|
ex = mt5bridge_ccxt.mt5bridge(exchange_config)
|
|
result = asyncio.run(
|
|
ex.watch_ohlcv("XAU/USD", "1h", limit=2,
|
|
params={"poll_interval_ms": 50, "max_wait_ms": 500})
|
|
)
|
|
assert len(result) >= 2
|
|
# New bar should be at the end with time 13:00
|
|
assert result[-1][0] == ex._parse_datetime("2026-07-08T13:00:00")
|