fix: sync live TP/SL to position cards after entrust changes

Use exchange TP/SL for display and DB sync on price_snapshot polls, refresh instance UI cells on each tick, and merge live values into hub monitor board.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-09 11:06:27 +08:00
parent 7cb55f6557
commit f7d94f67d7
12 changed files with 291 additions and 89 deletions
+9
View File
@@ -1269,6 +1269,15 @@ def _merge_flask_order_price_fields(hub_mon: dict | None, snap: dict | None) ->
o["rr_ratio"] = op["rr_ratio"]
if "sl_breakeven_secured" in op:
o["sl_breakeven_secured"] = bool(op["sl_breakeven_secured"])
for key in (
"stop_loss",
"take_profit",
"stop_loss_display",
"take_profit_display",
"display_rr_ratio",
):
if key in op and op[key] not in (None, ""):
o[key] = op[key]
def _merge_flask_position_breakeven(agent_row: dict, snap: dict | None, hub_mon: dict | None) -> None:
+34 -24
View File
@@ -1032,33 +1032,33 @@
return out;
}
function upsertExTpslCondOrder(cond, role, slot) {
if (!slot || slot.trigger_price == null || slot.trigger_price === "") return;
const label = role === "sl" ? "止损" : "止盈";
const item = {
label: label,
trigger_price: Number(slot.trigger_price),
amount: slot.amount != null ? slot.amount : null,
id: slot.order_id || "",
channel: "algo",
};
const idx = cond.findIndex(function (o) {
const lb = o.label || "";
return role === "sl" ? /^止损\b/.test(lb) || lb.includes("止损") : /^止盈\b/.test(lb) || lb.includes("止盈");
});
if (idx >= 0) cond[idx] = Object.assign({}, cond[idx], item);
else cond.push(item);
}
function condOrdersFromPosition(pos) {
const cond = dedupeCondOrdersByTrigger(
Array.isArray(pos.conditional_orders) ? pos.conditional_orders : []
);
if (cond.length) return cond;
const et = pos.exchange_tpsl;
if (!et) return [];
const out = [];
if (et.sl && et.sl.trigger_price != null) {
out.push({
label: "止损",
trigger_price: Number(et.sl.trigger_price),
amount: null,
id: et.sl.order_id,
channel: "algo",
});
}
if (et.tp && et.tp.trigger_price != null) {
out.push({
label: "止盈",
trigger_price: Number(et.tp.trigger_price),
amount: null,
id: et.tp.order_id,
channel: "algo",
});
}
return out;
if (!et) return cond;
upsertExTpslCondOrder(cond, "sl", et.sl);
upsertExTpslCondOrder(cond, "tp", et.tp);
return cond;
}
function findMonitorOrder(orders, symbol, side) {
@@ -1459,8 +1459,18 @@
}
const inferred = inferTpslFromCondOrders(pos.side, cond, entryN);
if (sl === "" || sl == null) sl = inferred.sl;
if (!tpMonitored && (takeProfit === "" || takeProfit == null)) takeProfit = inferred.tp;
if (inferred.sl !== "" && inferred.sl != null) {
sl = inferred.sl;
} else if (sl === "" || sl == null) {
sl = inferred.sl;
}
if (!tpMonitored) {
if (inferred.tp !== "" && inferred.tp != null) {
takeProfit = inferred.tp;
} else if (takeProfit === "" || takeProfit == null) {
takeProfit = inferred.tp;
}
}
if (sl !== "" && takeProfit !== "" && Number(sl) === Number(takeProfit)) {
takeProfit = "";