|
|
@@ -6,6 +6,7 @@ from tempfile import TemporaryDirectory
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
from src.trader_mcp import strategy_registry, strategy_store, strategy_engine
|
|
|
+from src.trader_mcp import server as trader_server
|
|
|
from src.trader_mcp.server import app, apply_control_decision
|
|
|
|
|
|
|
|
|
@@ -362,3 +363,45 @@ def test_apply_control_decision_rejects_expected_active_mismatch(tmp_path):
|
|
|
strategy_store.DB_PATH = original_db
|
|
|
strategy_registry.STRATEGIES_DIR = original_dir
|
|
|
strategy_engine._running.clear()
|
|
|
+
|
|
|
+
|
|
|
+def test_apply_control_decision_switches_even_when_current_is_degraded(tmp_path, monkeypatch):
|
|
|
+ original_db = strategy_store.DB_PATH
|
|
|
+ original_dir = strategy_registry.STRATEGIES_DIR
|
|
|
+ try:
|
|
|
+ strategy_store.DB_PATH = tmp_path / "trader_mcp.sqlite3"
|
|
|
+ strategy_registry.STRATEGIES_DIR = tmp_path / "strategies"
|
|
|
+ strategy_registry.STRATEGIES_DIR.mkdir()
|
|
|
+ (strategy_registry.STRATEGIES_DIR / "hello_world.py").write_text(STRATEGY_CODE)
|
|
|
+ (strategy_registry.STRATEGIES_DIR / "demo.py").write_text(STRATEGY_CODE)
|
|
|
+
|
|
|
+ strategy_store.add_strategy_instance(id="old", strategy_type="hello_world", account_id="acct-1", client_id="cid-old", mode="active", market_symbol="xrpusd", base_currency="XRP", counter_currency="USD", config={})
|
|
|
+ strategy_store.add_strategy_instance(id="new", strategy_type="demo", account_id="acct-1", client_id="cid-new", mode="off", market_symbol="xrpusd", base_currency="XRP", counter_currency="USD", config={})
|
|
|
+ strategy_engine.reconcile_all()
|
|
|
+
|
|
|
+ monkeypatch.setattr(trader_server, "_is_degraded", lambda instance_id: True)
|
|
|
+
|
|
|
+ result = apply_control_decision(
|
|
|
+ {
|
|
|
+ "decision_id": "dec-switch-degraded-1",
|
|
|
+ "concern_id": "acct-1:xrpusd",
|
|
|
+ "account_id": "acct-1",
|
|
|
+ "market_symbol": "xrpusd",
|
|
|
+ "action": "switch",
|
|
|
+ "target_strategy_id": "new",
|
|
|
+ "expected_active_strategy_id": "old",
|
|
|
+ "reason": "trend fits better",
|
|
|
+ "confidence": 0.9,
|
|
|
+ }
|
|
|
+ )
|
|
|
+ assert result["ok"] is True
|
|
|
+ assert result["status"] == "applied"
|
|
|
+ assert result["validation"]["current_degraded"] is True
|
|
|
+ assert result["result"].get("current_degraded") is True
|
|
|
+ assert result["result"].get("warning")
|
|
|
+ assert strategy_store.get_strategy_instance("old").mode == "off"
|
|
|
+ assert strategy_store.get_strategy_instance("new").mode == "active"
|
|
|
+ finally:
|
|
|
+ strategy_store.DB_PATH = original_db
|
|
|
+ strategy_registry.STRATEGIES_DIR = original_dir
|
|
|
+ strategy_engine._running.clear()
|