Support dual breakout targets for options-options hedges.

Replace single S* with up/down targets across UI, preview, persist, monitor, and alerts so ranging breakouts can close the winner either way.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-14 14:32:06 +08:00
parent f6ef06f659
commit 8ecc70a61c
13 changed files with 233 additions and 53 deletions
+33 -11
View File
@@ -324,8 +324,14 @@
fillExpSelect($("hp-oo-exp-select"), d);
renderListStrikes();
renderTStrikes();
if (d.index_px && $("hp-target") && !$("hp-target").value) {
$("hp-target").value = d.index_px;
if (d.index_px) {
const idx = Number(d.index_px);
if ($("hp-target-up") && !$("hp-target-up").value) {
$("hp-target-up").value = String(Math.round(idx * 1.03));
}
if ($("hp-target-down") && !$("hp-target-down").value) {
$("hp-target-down").value = String(Math.round(idx * 0.97));
}
}
}
@@ -583,7 +589,8 @@
if ($("hp-contracts")) $("hp-contracts").value = "";
if ($("hp-tp")) $("hp-tp").value = "";
if ($("hp-sl")) $("hp-sl").value = "";
if ($("hp-target")) $("hp-target").value = "";
if ($("hp-target-up")) $("hp-target-up").value = "";
if ($("hp-target-down")) $("hp-target-down").value = "";
if ($("hp-sel-inst")) $("hp-sel-inst").textContent = "—";
if ($("hp-premium-line")) $("hp-premium-line").textContent = "";
if ($("hp-oo-sheets-a")) {
@@ -606,12 +613,16 @@
let body;
if (isOo) {
if (!state.legA || !state.legB) throw new Error("请选用两条期权腿");
const target = Number(($("hp-target") && $("hp-target").value) || 0);
if (!target) throw new Error("请填写目标价");
const up = Number(($("hp-target-up") && $("hp-target-up").value) || 0);
const down = Number(($("hp-target-down") && $("hp-target-down").value) || 0);
if (!up || !down) throw new Error("请填写上破与下破目标价");
if (up <= down) throw new Error("上破目标价必须大于下破目标价");
body = {
plan_type: "options_options",
target_price: target,
index_px: (state.chain && state.chain.index_px) || target,
target_price_up: up,
target_price_down: down,
target_price: up,
index_px: (state.chain && state.chain.index_px) || (up + down) / 2,
leg_a: legPayload(state.legA, ooSheets("hp-oo-sheets-a")),
leg_b: legPayload(state.legB, ooSheets("hp-oo-sheets-b")),
};
@@ -862,6 +873,8 @@
oo_expiry_loss: "期期到期亏损",
oo_expiry_win: "期期到期盈利",
target_win_leg: "期期平盈利腿",
target_up_win_leg: "期期上破·平盈利腿",
target_down_win_leg: "期期下破·平盈利腿",
expiry: "到期",
manual: "人工结束",
partial_fail: "半腿失败",
@@ -930,7 +943,12 @@
fmt(p.perp_size, 4) +
"</div>";
} else {
html += "<div><span class=\"muted\">目标价 S*</span> " + fmt(p.target_price) + "</div>";
html +=
"<div><span class=\"muted\">目标价</span> 上破 " +
fmt(p.target_price_up || p.target_price) +
" · 下破 " +
fmt(p.target_price_down || p.target_price) +
"</div>";
}
html +=
"<div><span class=\"muted\">权利金合计</span> " +
@@ -1084,12 +1102,16 @@
let body;
if (isOo) {
if (!state.legA || !state.legB) throw new Error("请选用两条期权腿");
const target = Number(($("hp-target") && $("hp-target").value) || 0);
if (!target) throw new Error("请填写目标价");
const up = Number(($("hp-target-up") && $("hp-target-up").value) || 0);
const down = Number(($("hp-target-down") && $("hp-target-down").value) || 0);
if (!up || !down) throw new Error("请填写上破与下破目标价");
if (up <= down) throw new Error("上破目标价必须大于下破目标价");
body = {
plan_type: "options_options",
underlying: state.underlying,
target_price: target,
target_price_up: up,
target_price_down: down,
target_price: up,
leg_a: legPayload(state.legA, ooSheets("hp-oo-sheets-a")),
leg_b: legPayload(state.legB, ooSheets("hp-oo-sheets-b")),
};
+16
View File
@@ -3403,6 +3403,22 @@ html[data-theme="light"] .opt-be-dist-down {
background: rgba(255, 255, 255, 0.03);
font-size: 0.78rem;
}
.hedge-plan-page-wrap .hp-target-row {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
margin: 6px 0;
}
.hedge-plan-page-wrap .hp-target-row label {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 0.8rem;
}
.hedge-plan-page-wrap .hp-target-row input {
width: 110px;
}
.hedge-plan-page-wrap .hp-contracts-cell {
max-width: 220px;
overflow: hidden;