Add option-option hedge mode with SIM/LIVE parity.

Mutual hedge_mode, amplitude OTM selection, 1:1 risk sizing, win-leg/full close, dual audits and docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-07 16:01:16 +08:00
parent 15fe2f72dc
commit ec244c63c6
22 changed files with 2640 additions and 83 deletions
+70 -4
View File
@@ -213,7 +213,7 @@ export default function PlanPage() {
const riskRatioLabel = `比例${Number(plan?.risk_perp_unit ?? 1)}:${Number(plan?.risk_option_unit ?? 2)}`;
const sizingModeLabel = riskBased
? [
"以损定仓",
plan?.hedge_mode === "option_option" ? "期期对冲" : "以损定仓",
riskRatioLabel,
plan?.risk_last_k != null ? `k=${fmt(plan.risk_last_k, 1)}` : null,
riskLocked
@@ -236,7 +236,9 @@ export default function PlanPage() {
]
.filter(Boolean)
.join(" ")
: "手动仓位";
: plan?.hedge_mode === "option_option"
? "期期对冲"
: "手动仓位";
const phaseLabel = PHASE_ZH[plan?.phase || ""] || plan?.phase || "—";
const atmRule = plan?.fixed_direction_enabled
? plan?.fixed_perp_side === "short"
@@ -581,6 +583,57 @@ export default function PlanPage() {
<div className="plan-positions">
{open ? (
<>
{plan?.hedge_mode === "option_option" ||
pos?.hedge_mode === "option_option" ||
pos?.option2_inst_id ? (
<div className="pos-card">
<div className="pos-card-head">
<div className="pos-card-symbol">
<strong>
{pos?.option_inst_id || "Call"}
</strong>
<span className="pos-side-badge pos-side-long">
Call
</span>
</div>
</div>
<div className="pos-meta">
<span className="pos-meta-item"> · Call</span>
<span className="pos-meta-item"> {pos?.group_id}</span>
<span className="pos-meta-item mono">
{fmt(pos?.option_qty_eth, 1)} ETH
</span>
</div>
<div className="pos-grid">
<div className="pos-cell">
<span className="pos-label"></span>
<span className="pos-value mono">
{fmt(pos?.option_entry_px)}
</span>
</div>
<div className="pos-cell">
<span className="pos-label"></span>
<span
className={`pos-value mono ${pnlClass(pos?.option_upl)}`}
>
{fmt(pos?.option_upl)}
</span>
</div>
<div className="pos-cell">
<span className="pos-label"></span>
<span className="pos-value mono">
{fmt(pos?.strike, 0)}
</span>
</div>
<div className="pos-cell">
<span className="pos-label"></span>
<span className="pos-value mono">
{holdDurationLabel}
</span>
</div>
</div>
</div>
) : (
<div className="pos-card">
<div className="pos-card-head">
<div className="pos-card-symbol">
@@ -649,19 +702,32 @@ export default function PlanPage() {
</div>
</div>
</div>
)}
<div className="pos-card">
<div className="pos-card-head">
<div className="pos-card-symbol">
<strong>{pos?.option_inst_id || "期权"}</strong>
<strong>
{plan?.hedge_mode === "option_option" ||
pos?.option2_inst_id
? pos?.option2_inst_id || "Put"
: pos?.option_inst_id || "期权"}
</strong>
<span
className={
plan?.hedge_mode === "option_option" ||
pos?.option2_inst_id ||
pos?.option_side === "call"
? "pos-side-badge pos-side-long"
: "pos-side-badge pos-side-short"
}
>
{pos?.option_side === "call" ? "看涨 Call" : "看跌 Put"}
{plan?.hedge_mode === "option_option" ||
pos?.option2_inst_id
? "看跌 Put"
: pos?.option_side === "call"
? "看涨 Call"
: "看跌 Put"}
</span>
</div>
<div