fix(hub): sync TP/SL display after trend handoff to order monitor

Use order monitor plan prices on handoff cards and fill exchange TP/SL rows when Gate shows reduce-only orders without algo labels.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-04 19:39:11 +08:00
parent e39fac2c16
commit ed0805538f
4 changed files with 109 additions and 18 deletions
+46 -5
View File
@@ -697,28 +697,59 @@ def _tpsl_slots_to_conditional_orders(exchange_tpsl: dict, symbol: str) -> list[
if not isinstance(slot, dict):
continue
trig = slot.get("trigger_price")
oid = slot.get("order_id")
if trig is None or oid is None:
if trig is None:
continue
try:
trig_f = float(trig)
except (TypeError, ValueError):
continue
oid = slot.get("order_id")
out.append(
{
"id": str(oid),
"id": str(oid) if oid is not None else "",
"symbol": symbol,
"channel": "algo",
"category": "conditional",
"label": f"{label} {trig_f:g}",
"trigger_price": trig_f,
"amount": None,
"amount": slot.get("amount"),
"status": "open",
}
)
return out
def _exchange_tpsl_from_hub_order(hub_orders: list, symbol: str, side: str) -> dict | None:
"""趋势保本移交后:用下单监控计划价补全 exchange_tpsl(与实例页一致)。"""
side_l = (side or "").lower()
for o in hub_orders:
if not isinstance(o, dict):
continue
o_sym = o.get("exchange_symbol") or o.get("symbol") or ""
if not _symbols_match(symbol, o_sym):
continue
if (o.get("direction") or "").lower() != side_l:
continue
sl = o.get("stop_loss")
tp = o.get("take_profit")
if sl in (None, "") and tp in (None, ""):
continue
slots: dict = {"sl": None, "tp": None}
if sl not in (None, ""):
try:
slots["sl"] = {"trigger_price": float(sl), "order_id": None}
except (TypeError, ValueError):
pass
if tp not in (None, ""):
try:
slots["tp"] = {"trigger_price": float(tp), "order_id": None}
except (TypeError, ValueError):
pass
if slots["sl"] or slots["tp"]:
return slots
return None
def _find_exchange_tpsl_for_position(
symbol: str,
side: str,
@@ -946,12 +977,22 @@ def _merge_flask_exchange_tpsl(agent_row: dict, snap: dict | None, hub_mon: dict
sym = p.get("symbol") or ""
side = p.get("side") or ""
et = _find_exchange_tpsl_for_position(sym, side, order_prices, hub_orders)
if not et:
et = _exchange_tpsl_from_hub_order(hub_orders, sym, side)
if not et:
continue
p["exchange_tpsl"] = et
cond = p.get("conditional_orders") or []
merged = _tpsl_slots_to_conditional_orders(et, sym)
if not cond:
p["conditional_orders"] = _tpsl_slots_to_conditional_orders(et, sym)
p["conditional_orders"] = merged
elif merged:
labels = {str(c.get("label") or "") for c in cond if isinstance(c, dict)}
for row in merged:
lbl = str(row.get("label") or "")
if lbl and not any(lbl in x or x in lbl for x in labels):
cond.append(row)
p["conditional_orders"] = cond
async def _fetch_exchange_flask_bundle(