"""Tests for MQL5 GlobalVariable bridge.""" import responses import pytest import mt5bridge_ccxt class TestMql5Bridge: @responses.activate def test_list(self, exchange_config): responses.add( responses.GET, "http://mock-mt5bridge:8080/gvar", json={"data": [ {"name": "AT_Trend_XAUUSD", "value": 1.0}, {"name": "AT_Buy_XAUUSD", "value": 1.0}, ], "count": 2, "format": "json"}, status=200, ) ex = mt5bridge_ccxt.mt5bridge(exchange_config) gvars = ex.mql5.list() assert len(gvars) == 2 assert gvars[0]["name"] == "AT_Trend_XAUUSD" @responses.activate def test_get_existing(self, exchange_config): responses.add( responses.GET, "http://mock-mt5bridge:8080/gvar/AT_Trend_XAUUSD", json={"name": "AT_Trend_XAUUSD", "value": 1.0}, status=200, ) ex = mt5bridge_ccxt.mt5bridge(exchange_config) assert ex.mql5.get("AT_Trend_XAUUSD") == 1.0 @responses.activate def test_get_missing_returns_default(self, exchange_config): responses.add( responses.GET, "http://mock-mt5bridge:8080/gvar/MISSING", json={"detail": "Not found"}, status=404, ) ex = mt5bridge_ccxt.mt5bridge(exchange_config) assert ex.mql5.get("MISSING") is None assert ex.mql5.get("MISSING", default=42) == 42 @responses.activate def test_set(self, exchange_config): responses.add( responses.POST, "http://mock-mt5bridge:8080/gvar/MY_KEY", json={"name": "MY_KEY", "value": 75.5}, status=200, ) ex = mt5bridge_ccxt.mt5bridge(exchange_config) result = ex.mql5.set("MY_KEY", 75.5) assert result["name"] == "MY_KEY" @responses.activate def test_alpha_trend_signal(self, exchange_config): # Mock 5 GV lookups gv_data = { "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Alpha": {"name": "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Alpha", "value": 4180.0}, "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Offset": {"name": "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Offset", "value": 4178.0}, "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Trend": {"name": "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Trend", "value": 1.0}, "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Buy": {"name": "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Buy", "value": 1.0}, "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Sell": {"name": "AT_XAUUSDc_PERIOD_H1_L14_A1.0_C0_S1_Sell", "value": 0.0}, } for path, payload in gv_data.items(): responses.add( responses.GET, f"http://mock-mt5bridge:8080/gvar/{path}", json=payload, status=200, ) ex = mt5bridge_ccxt.mt5bridge(exchange_config) signal = ex.mql5.alpha_trend_signal("XAUUSDc", "H1", length=14, atr_mult=1.0) assert signal["alpha"] == 4180.0 assert signal["trend"] == 1.0 assert signal["buy"] == 1.0 assert signal["sell"] == 0.0 class TestTimeframeConversion: def test_to_mt5(self): from mt5bridge_ccxt.timeframe import to_mt5 assert to_mt5("1m") == "TIMEFRAME_M1" assert to_mt5("1h") == "TIMEFRAME_H1" assert to_mt5("1d") == "TIMEFRAME_D1" def test_to_mt5_invalid(self): from mt5bridge_ccxt.timeframe import to_mt5 with pytest.raises(ValueError): to_mt5("2h") def test_to_ccxt(self): from mt5bridge_ccxt.timeframe import to_ccxt assert to_ccxt("TIMEFRAME_M1") == "1m" assert to_ccxt("TIMEFRAME_H1") == "1h" assert to_ccxt("TIMEFRAME_D1") == "1d" class TestSymbolConversion: def test_to_mt5_with_slash(self): from mt5bridge_ccxt.symbol import to_mt5_symbol assert to_mt5_symbol("XAU/USD") == "XAUUSD" assert to_mt5_symbol("EUR/USD") == "EURUSD" def test_to_mt5_already_mt5(self): from mt5bridge_ccxt.symbol import to_mt5_symbol assert to_mt5_symbol("XAUUSDc") == "XAUUSDc" def test_to_mt5_with_suffix(self): from mt5bridge_ccxt.symbol import to_mt5_symbol assert to_mt5_symbol("XAU/USD", default_suffix="c") == "XAUUSDc" def test_to_ccxt_simple(self): from mt5bridge_ccxt.symbol import to_ccxt_symbol assert to_ccxt_symbol("XAUUSD") == "XAU/USD" assert to_ccxt_symbol("EURUSD") == "EUR/USD" def test_to_ccxt_with_suffix(self): from mt5bridge_ccxt.symbol import to_ccxt_symbol assert to_ccxt_symbol("XAUUSDc") == "XAU/USD" assert to_ccxt_symbol("EURUSDc") == "EUR/USD" def test_to_ccxt_with_explicit_quote(self): from mt5bridge_ccxt.symbol import to_ccxt_symbol # Ambiguous case: split on explicit quote assert to_ccxt_symbol("XAUUSD", quote="USD") == "XAU/USD"