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:
@@ -455,6 +455,11 @@
|
||||
return side || "—";
|
||||
}
|
||||
|
||||
function isTrendHandoffOrder(monitorOrder) {
|
||||
const mo = monitorOrder || {};
|
||||
return String(mo.trade_style || "").toLowerCase() === "trend_pullback_handoff";
|
||||
}
|
||||
|
||||
function isTrendContext(monitorOrder, trendPlan) {
|
||||
const mo = monitorOrder || {};
|
||||
const tp = trendPlan || {};
|
||||
@@ -1176,20 +1181,36 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
function orderTriggerOrPrice(o) {
|
||||
if (!o) return null;
|
||||
if (o.trigger_price != null && o.trigger_price !== "") {
|
||||
const t = Number(o.trigger_price);
|
||||
if (Number.isFinite(t) && t > 0) return t;
|
||||
}
|
||||
if (o.price != null && o.price !== "") {
|
||||
const p = Number(o.price);
|
||||
if (Number.isFinite(p) && p > 0) return p;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function inferTpslFromCondOrders(side, cond, entry) {
|
||||
const picked = pickExTpslOrders(cond);
|
||||
let sl = picked.sl && picked.sl.trigger_price != null ? picked.sl.trigger_price : "";
|
||||
let tp = picked.tp && picked.tp.trigger_price != null ? picked.tp.trigger_price : "";
|
||||
let sl = picked.sl ? orderTriggerOrPrice(picked.sl) : "";
|
||||
let tp = picked.tp ? orderTriggerOrPrice(picked.tp) : "";
|
||||
if (sl !== "" && sl != null) sl = Number(sl);
|
||||
if (tp !== "" && tp != null) tp = Number(tp);
|
||||
if (sl !== "" && tp !== "" && Number(sl) !== Number(tp)) {
|
||||
return { sl, tp };
|
||||
}
|
||||
|
||||
const triggers = (cond || [])
|
||||
.map(function (o) {
|
||||
return { price: Number(o.trigger_price), label: o.label || "" };
|
||||
const px = orderTriggerOrPrice(o);
|
||||
return px == null ? null : { price: px, label: o.label || "" };
|
||||
})
|
||||
.filter(function (o) {
|
||||
return o.price != null && !Number.isNaN(o.price) && o.price > 0;
|
||||
return o != null;
|
||||
});
|
||||
if (!triggers.length) return { sl: sl || "", tp: tp || "" };
|
||||
|
||||
@@ -1270,12 +1291,15 @@
|
||||
: tp.avg_entry_price;
|
||||
const entryN = entryRaw != null && entryRaw !== "" ? Number(entryRaw) : null;
|
||||
const isTrend = isTrendContext(mo, trendPlan);
|
||||
const handoff = isTrendHandoffOrder(mo);
|
||||
|
||||
let sl = mo.stop_loss != null && mo.stop_loss !== "" ? mo.stop_loss : "";
|
||||
let takeProfit = mo.take_profit != null && mo.take_profit !== "" ? mo.take_profit : "";
|
||||
let tpMonitored = false;
|
||||
|
||||
if (isTrend) {
|
||||
if (handoff) {
|
||||
tpMonitored = false;
|
||||
} else if (isTrend) {
|
||||
tpMonitored = true;
|
||||
if (trendPlan && trendPlan.stop_loss != null && trendPlan.stop_loss !== "") {
|
||||
sl = trendPlan.stop_loss;
|
||||
@@ -1301,6 +1325,7 @@
|
||||
tp: takeProfit,
|
||||
tp_monitored: tpMonitored,
|
||||
is_trend: isTrend,
|
||||
is_handoff: handoff,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1568,6 +1593,18 @@
|
||||
</details>`;
|
||||
}
|
||||
|
||||
function syntheticExTpslOrder(role, price, amount) {
|
||||
if (price == null || price === "" || !Number.isFinite(Number(price))) return null;
|
||||
return {
|
||||
label: role === "sl" ? "止损" : "止盈",
|
||||
trigger_price: Number(price),
|
||||
price: Number(price),
|
||||
amount: amount != null ? amount : null,
|
||||
id: "",
|
||||
channel: "plan",
|
||||
};
|
||||
}
|
||||
|
||||
function pickExTpslOrders(cond) {
|
||||
let sl = cond.find((o) => /^止损\b/.test(o.label || ""));
|
||||
let tp = cond.find((o) => /^止盈\b/.test(o.label || "") && !(o.label || "").includes("止盈止损"));
|
||||
@@ -1586,20 +1623,32 @@
|
||||
return { sl, tp };
|
||||
}
|
||||
|
||||
function renderExTpslRows(exchangeId, symbol, cond, tickMap) {
|
||||
function renderExTpslRows(exchangeId, symbol, cond, tickMap, resolvedTpsl, contracts) {
|
||||
const symAttr = esc(symbol || "").replace(/"/g, """);
|
||||
const { sl, tp } = pickExTpslOrders(cond);
|
||||
let { sl, tp } = pickExTpslOrders(cond);
|
||||
const plan = resolvedTpsl || {};
|
||||
if (!sl && plan.sl != null && plan.sl !== "") {
|
||||
sl = syntheticExTpslOrder("sl", plan.sl, contracts);
|
||||
}
|
||||
if (!tp && plan.tp != null && plan.tp !== "") {
|
||||
tp = syntheticExTpslOrder("tp", plan.tp, contracts);
|
||||
}
|
||||
function row(label, o) {
|
||||
if (!o) {
|
||||
return `<div class="pos-ex-order-row"><span class="pos-ex-order-main">${label}:—</span></div>`;
|
||||
}
|
||||
const oid = esc(o.id || "").replace(/"/g, """);
|
||||
const ch = esc(o.channel || "regular").replace(/"/g, """);
|
||||
const trig =
|
||||
o.trigger_price != null ? fmtSymbolPrice(o.trigger_price, symbol, tickMap) : "—";
|
||||
const px = orderTriggerOrPrice(o);
|
||||
const trig = px != null ? fmtSymbolPrice(px, symbol, tickMap) : "—";
|
||||
const cancelBtn =
|
||||
oid && o.channel !== "plan"
|
||||
? `<button type="button" class="pos-ex-cancel-btn btn-cancel-order" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-order-id="${oid}" data-channel="${ch}">撤单</button>`
|
||||
: "";
|
||||
const planHint = o.channel === "plan" ? '<span class="pos-ex-plan-hint">(下单监控)</span>' : "";
|
||||
return `<div class="pos-ex-order-row">
|
||||
<span class="pos-ex-order-main">${label}:触发 ${trig} · 数量 ${fmt(o.amount, 4)}</span>
|
||||
<button type="button" class="pos-ex-cancel-btn btn-cancel-order" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-order-id="${oid}" data-channel="${ch}">撤单</button>
|
||||
<span class="pos-ex-order-main">${label}:触发 ${trig} · 数量 ${fmt(o.amount, 4)}${planHint}</span>
|
||||
${cancelBtn}
|
||||
</div>`;
|
||||
}
|
||||
return row("止损", sl) + row("止盈", tp);
|
||||
@@ -1884,7 +1933,7 @@
|
||||
</div>
|
||||
<div class="pos-ex-orders">
|
||||
<div class="pos-ex-orders-title">交易所止盈止损</div>
|
||||
${renderExTpslRows(exchangeId, symbol, cond, tickMap)}
|
||||
${renderExTpslRows(exchangeId, symbol, cond, tickMap, tpsl, pos.contracts)}
|
||||
</div>
|
||||
${renderOrdersCollapse(exchangeId, symbol, cond, reg, tickMap)}
|
||||
</div>`;
|
||||
|
||||
Reference in New Issue
Block a user