Park partial hedge plans for manual leg complete instead of auto-close.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-19 09:06:22 +08:00
parent e11c13747a
commit d74d0aeae0
10 changed files with 540 additions and 64 deletions
+66 -3
View File
@@ -1198,6 +1198,51 @@
return "上破 " + fmt(p.target_price_up || p.target_price) + " · 下破 " + fmt(p.target_price_down || p.target_price);
}
function activeStatusLabel(p) {
if ((p.status || "") === "partial") {
return '<span class="hp-plan-partial">半腿待补</span>';
}
if ((p.status || "") === "opening") {
return '<span class="hp-plan-active">开仓中</span>';
}
return '<span class="hp-plan-active">进行中</span>';
}
function completeLegButtonHtml(p) {
if ((p.status || "") !== "partial") return "";
const role = p.missing_leg || "";
let label = "";
if (role === "perp") label = "补开永续";
else if (role === "option_b") label = "补开腿B";
else if (role === "option_hedge" || role === "option_a") label = "补开期权";
else return "";
return (
'<button type="button" class="primary hp-btn-complete" data-id="' +
p.id +
'" data-role="' +
role +
'">' +
label +
"</button>"
);
}
async function completeMissingLeg(planId) {
if (!window.confirm("确认补开缺失腿并真实下单?")) return;
try {
const d = await apiJson("/api/hedge-plan/" + planId + "/complete-leg", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
});
alert("补开成功 #" + (d.plan_id || planId) + " · 已进入进行中");
void loadActivePlans();
void loadGates();
} catch (e) {
alert(e.message || String(e));
}
}
async function loadActivePlans() {
const tbody = $("hp-active-tbody");
if (!tbody) return;
@@ -1225,12 +1270,14 @@
"\"><code>" +
contracts +
"</code></td><td>" +
'<span class="hp-plan-active">进行中</span>' +
activeStatusLabel(p) +
"</td><td>" +
activeTargetLabel(p) +
"</td><td>" +
(p.opened_at || "—") +
'</td><td class="hp-hist-actions"><button type="button" class="btn-secondary hp-btn-detail" data-id="' +
'</td><td class="hp-hist-actions">' +
completeLegButtonHtml(p) +
'<button type="button" class="btn-secondary hp-btn-detail" data-id="' +
p.id +
'">成交细节</button></td>';
tbody.appendChild(tr);
@@ -1240,6 +1287,11 @@
void showPlanDetail(Number(btn.getAttribute("data-id")));
});
});
tbody.querySelectorAll(".hp-btn-complete").forEach(function (btn) {
btn.addEventListener("click", function () {
void completeMissingLeg(Number(btn.getAttribute("data-id")));
});
});
} catch (e) {
tbody.innerHTML = '<tr><td colspan="8" class="err">' + (e.message || e) + "</td></tr>";
}
@@ -1532,7 +1584,18 @@
});
setGateLine(d.gates);
closePreviewModal();
alert("计划已启动 #" + (d.plan_id || "") + (d.dry_run ? " (dry_run)" : ""));
if (d.partial) {
alert(
(d.msg || "半腿失败,已挂待补") +
(d.plan_id ? "\n计划 #" + d.plan_id : "") +
"\n请到「进行中的计划」补开缺失腿"
);
state.tab = "active";
syncTabUI();
void loadActivePlans();
} else {
alert("计划已启动 #" + (d.plan_id || "") + (d.dry_run ? " (dry_run)" : ""));
}
void loadGates();
} catch (e) {
alert(e.message || String(e));
+10
View File
@@ -3249,6 +3249,16 @@ html[data-theme="light"] .opt-be-dist-down {
color: #7ee787;
font-weight: 700;
}
.hedge-plan-page-wrap .hp-plan-partial {
color: #ffb454;
font-weight: 700;
}
.hedge-plan-page-wrap .hp-hist-actions .hp-btn-complete {
margin-right: 6px;
padding: 3px 8px;
font-size: 0.72rem;
min-height: 26px;
}
.hedge-plan-page-wrap .hp-pnl-neg {
color: #ff8a8a;
}