Fix false supervisor open events for existing holdings

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-23 20:20:33 +08:00
parent 65901c5577
commit 54ba412d1d
2 changed files with 122 additions and 16 deletions
+54 -12
View File
@@ -30,10 +30,10 @@ def test_classify_close_result():
def test_detect_new_opens():
prev = {"0|ETH/USDT|long": {"symbol": "ETH/USDT"}}
prev = {"0|ETH/USDT|long": {"symbol": "ETH/USDT", "contracts": 1.0}}
curr = {
"0|ETH/USDT|long": {"symbol": "ETH/USDT"},
"1|BTC/USDT|short": {"symbol": "BTC/USDT", "exchange_name": "OKX"},
"0|ETH/USDT|long": {"symbol": "ETH/USDT", "contracts": 1.0},
"1|BTC/USDT|short": {"symbol": "BTC/USDT", "contracts": 2.0, "exchange_name": "OKX"},
}
events = sup.detect_new_opens(prev, curr)
assert len(events) == 1
@@ -41,6 +41,31 @@ def test_detect_new_opens():
assert events[0]["symbol"] == "BTC/USDT"
def test_detect_new_opens_skips_existing_holdings():
prev = {
"2|ZEC/USDT|short": {"symbol": "ZEC/USDT:USDT", "contracts": 5.0},
"2|HYPE/USDT|short": {"symbol": "HYPE/USDT:USDT", "contracts": 3.0},
}
curr = {
"2|ZEC/USDT|short": {"symbol": "ZEC/USDT:USDT", "contracts": 5.0},
"2|HYPE/USDT|short": {"symbol": "HYPE/USDT:USDT", "contracts": 3.0},
}
assert sup.detect_new_opens(prev, curr) == []
def test_detect_new_opens_only_from_flat():
prev = {"2|ZEC/USDT|short": {"symbol": "ZEC/USDT", "contracts": 0.0}}
curr = {"2|ZEC/USDT|short": {"symbol": "ZEC/USDT:USDT", "contracts": 2.0}}
events = sup.detect_new_opens(prev, curr)
assert len(events) == 1
assert events[0]["symbol"] == "ZEC/USDT:USDT"
def test_normalize_position_symbol():
assert sup._normalize_position_symbol("ZEC/USDT:USDT") == "ZEC/USDT"
assert sup._position_key("2", "ZEC/USDT:USDT", "short") == "2|ZEC/USDT|short"
def test_detect_new_closes_dedup():
trades = [
{
@@ -100,7 +125,10 @@ def test_process_supervisor_tick_seeds_without_events(state_path, monkeypatch, t
}
],
}
board = {"ok": True, "rows": []}
board = {
"ok": True,
"rows": [{"id": "0", "enabled": True, "agent": {"ok": True, "positions": []}}],
}
settings = {"supervisor": sup.normalize_supervisor_settings({"enabled": True, "wechat_webhook": ""})}
r1 = sup.process_supervisor_tick(dash, board, settings, ai_reply_fn=None)
@@ -110,6 +138,26 @@ def test_process_supervisor_tick_seeds_without_events(state_path, monkeypatch, t
r2 = sup.process_supervisor_tick(dash, board, settings, ai_reply_fn=None)
assert r2.get("events") == 0
board2 = {
"ok": True,
"rows": [
{
"id": "2",
"name": "Gate",
"enabled": True,
"agent": {
"ok": True,
"positions": [
{"symbol": "ZEC/USDT:USDT", "side": "short", "contracts": 1.0},
{"symbol": "HYPE/USDT:USDT", "side": "short", "contracts": 1.0},
],
},
}
],
}
r3 = sup.process_supervisor_tick(dash, board2, settings, ai_reply_fn=None)
assert r3.get("events") == 0
dash2 = dict(dash)
dash2["closed_trades"] = dash["closed_trades"] + [
{
@@ -120,14 +168,8 @@ def test_process_supervisor_tick_seeds_without_events(state_path, monkeypatch, t
"closed_at": "2026-06-14 11:00:00",
}
]
r3 = sup.process_supervisor_tick(dash2, board, settings, ai_reply_fn=None)
assert r3.get("events") == 1
assert chat_path.is_file()
data = json.loads(chat_path.read_text(encoding="utf-8"))
sessions = [s for s in data.get("sessions") or [] if s.get("bot_mode") == "supervisor"]
assert sessions
msgs = sessions[0].get("messages") or []
assert any(m.get("role") == "system" for m in msgs)
r4 = sup.process_supervisor_tick(dash2, board2, settings, ai_reply_fn=None)
assert r4.get("events") == 1
def test_normalize_supervisor_settings_env(monkeypatch):