132 lines
4.9 KiB
Python
132 lines
4.9 KiB
Python
"""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"
|