Hide perp-option settings when option-option hedge is selected.

Show OO selection and reward-ratio fields in their tabs instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-07 16:21:36 +08:00
parent 8d3c181246
commit cd88fa5d83
+269 -180
View File
@@ -368,10 +368,12 @@ export default function SettingsPage() {
setStratOk(""); setStratOk("");
setErr(""); setErr("");
const isLive = mode === "LIVE"; const isLive = mode === "LIVE";
const oo = hedgeMode === "option_option";
try { try {
const body: Record<string, unknown> = { const body: Record<string, unknown> = {
fee_rate: fee, fee_rate: fee,
exit_mode: sizingMode === "risk_based" ? "fixed_usdt" : exitMode, exit_mode:
oo || sizingMode === "risk_based" ? "fixed_usdt" : exitMode,
premium_exit_multiple: premMult, premium_exit_multiple: premMult,
rest_seconds: rest, rest_seconds: rest,
live_order_interval_sec: orderInterval, live_order_interval_sec: orderInterval,
@@ -381,16 +383,16 @@ export default function SettingsPage() {
perp_margin_mode: perpMarginMode, perp_margin_mode: perpMarginMode,
min_option_hours: minHours, min_option_hours: minHours,
min_option_leverage: minOptLev, min_option_leverage: minOptLev,
atm_open_offset_enabled: atmOffOn, atm_open_offset_enabled: oo ? false : atmOffOn,
max_atm_open_offset: maxAtmOff, max_atm_open_offset: maxAtmOff,
fixed_direction_enabled: fixedDirOn, fixed_direction_enabled: oo ? false : fixedDirOn,
fixed_perp_side: fixedPerpSide, fixed_perp_side: fixedPerpSide,
close_bid_mark_max_pct: closeDevPct, close_bid_mark_max_pct: closeDevPct,
residual_min_premium_pct: residualMinPremPct, residual_min_premium_pct: residualMinPremPct,
show_manual_trade_buttons: showManualTrade, show_manual_trade_buttons: showManualTrade,
sizing_mode: sizingMode, sizing_mode: oo ? "risk_based" : sizingMode,
risk_leverage_basis: riskLeverageBasis, risk_leverage_basis: riskLeverageBasis,
risk_loss_mode: riskLossMode, risk_loss_mode: oo ? "percent" : riskLossMode,
risk_loss_pct: riskLossPct, risk_loss_pct: riskLossPct,
risk_loss_usdt: riskLossUsdt, risk_loss_usdt: riskLossUsdt,
risk_capital_source: riskCapitalSource, risk_capital_source: riskCapitalSource,
@@ -399,8 +401,8 @@ export default function SettingsPage() {
risk_option_unit: riskOptUnit, risk_option_unit: riskOptUnit,
risk_exit_unit: riskExitUnit, risk_exit_unit: riskExitUnit,
martingale_enabled: martingale_enabled:
sizingMode === "risk_based" && (oo || sizingMode === "risk_based") &&
riskLossMode === "percent" && (oo || riskLossMode === "percent") &&
riskLossPct <= 3 && riskLossPct <= 3 &&
martingaleOn, martingaleOn,
martingale_start_after_loss_days: martingaleStartAfter, martingale_start_after_loss_days: martingaleStartAfter,
@@ -543,6 +545,8 @@ export default function SettingsPage() {
} }
} }
const isOo = hedgeMode === "option_option";
return ( return (
<div className="settings-page"> <div className="settings-page">
<h2 style={{ marginTop: 0 }}></h2> <h2 style={{ marginTop: 0 }}></h2>
@@ -676,34 +680,40 @@ export default function SettingsPage() {
/> />
</div> </div>
) : null} ) : null}
<div className="field"> {!isOo ? (
<label htmlFor="lev"></label> <>
<input <div className="field">
id="lev" <label htmlFor="lev"></label>
className="mono" <input
type="number" id="lev"
step="1" className="mono"
min="1" type="number"
value={leverage} step="1"
onChange={(e) => setLeverage(Number(e.target.value))} min="1"
/> value={leverage}
</div> onChange={(e) => setLeverage(Number(e.target.value))}
<div className="field"> />
<label htmlFor="perpMm"></label> </div>
<select <div className="field">
id="perpMm" <label htmlFor="perpMm"></label>
className="mono" <select
value={perpMarginMode} id="perpMm"
onChange={(e) => className="mono"
setPerpMarginMode( value={perpMarginMode}
e.target.value === "isolated" ? "isolated" : "cross", onChange={(e) =>
) setPerpMarginMode(
} e.target.value === "isolated"
> ? "isolated"
<option value="cross"></option> : "cross",
<option value="isolated"></option> )
</select> }
</div> >
<option value="cross"></option>
<option value="isolated"></option>
</select>
</div>
</>
) : null}
<div className="field"> <div className="field">
<label htmlFor="hedgeMode"></label> <label htmlFor="hedgeMode"></label>
<select <select
@@ -730,145 +740,110 @@ export default function SettingsPage() {
N Call/Put N Call/Put
</p> </p>
</div> </div>
{hedgeMode === "option_option" ? ( {isOo ? (
<> <div className="field">
<div className="field"> <label htmlFor="ooRR"></label>
<label htmlFor="ooAmp">%</label> <input
<input id="ooRR"
id="ooAmp" className="mono"
className="mono" type="number"
type="number" step="0.1"
step="0.1" min="0.5"
min="0.1" value={ooRewardRatio}
value={ooAmpPct} onChange={(e) =>
onChange={(e) => setOoAmpPct(Number(e.target.value))} setOoRewardRatio(Number(e.target.value))
/> }
</div> />
<div className="field"> <p className="hint" style={{ margin: "0.35rem 0 0" }}>
<label htmlFor="ooAmpH"></label> = × 100U 2
<input 200U 1:1 /
id="ooAmpH" </p>
className="mono" </div>
type="number"
step="1"
min="1"
value={ooAmpHours}
onChange={(e) =>
setOoAmpHours(Number(e.target.value))
}
/>
</div>
<div className="field">
<label htmlFor="ooMinH"></label>
<input
id="ooMinH"
className="mono"
type="number"
step="1"
min="1"
value={ooMinHours}
onChange={(e) =>
setOoMinHours(Number(e.target.value))
}
/>
</div>
<div className="field">
<label htmlFor="ooLev"></label>
<input
id="ooLev"
className="mono"
type="number"
step="1"
min="1"
value={ooMinLev}
onChange={(e) => setOoMinLev(Number(e.target.value))}
/>
</div>
<div className="field">
<label htmlFor="ooRR"></label>
<input
id="ooRR"
className="mono"
type="number"
step="0.1"
min="0.5"
value={ooRewardRatio}
onChange={(e) =>
setOoRewardRatio(Number(e.target.value))
}
/>
<p className="hint" style={{ margin: "0.35rem 0 0" }}>
= × 100U 2
200U 1:1
</p>
</div>
</>
) : null} ) : null}
<div className="field"> {!isOo ? (
<label htmlFor="sizingMode"></label> <div className="field">
<select <label htmlFor="sizingMode"></label>
id="sizingMode" <select
className="mono" id="sizingMode"
value={sizingMode} className="mono"
disabled={hedgeMode === "option_option"} value={sizingMode}
onChange={(e) => onChange={(e) =>
setSizingMode( setSizingMode(
e.target.value === "risk_based" e.target.value === "risk_based"
? "risk_based" ? "risk_based"
: "manual", : "manual",
) )
} }
> >
<option value="manual"> ETH </option> <option value="manual"> ETH </option>
<option value="risk_based"></option> <option value="risk_based">
</select>
</div> </option>
{sizingMode === "risk_based" ? ( </select>
</div>
) : (
<div className="field">
<label></label>
<div className="mono" style={{ fontSize: 13 }}>
· Call/Put 1:1
</div>
</div>
)}
{sizingMode === "risk_based" || isOo ? (
<> <>
<div className="field"> {!isOo ? (
<label htmlFor="riskLevBasis"></label> <div className="field">
<select <label htmlFor="riskLevBasis">
id="riskLevBasis"
className="mono" </label>
value={riskLeverageBasis} <select
onChange={(e) => id="riskLevBasis"
setRiskLeverageBasis( className="mono"
e.target.value === "actual" value={riskLeverageBasis}
? "actual" onChange={(e) =>
: "selection", setRiskLeverageBasis(
) e.target.value === "actual"
} ? "actual"
> : "selection",
<option value="selection"> )
}
</option> >
<option value="actual"></option> <option value="selection">
</select>
<p className="hint" style={{ margin: "0.35rem 0 0" }}> </option>
÷ k便 <option value="actual"></option>
便 k </select>
</p> <p className="hint" style={{ margin: "0.35rem 0 0" }}>
</div> ÷
<div className="field"> k便
<label htmlFor="riskLossMode"></label> 便 k
<select </p>
id="riskLossMode" </div>
className="mono" ) : null}
value={riskLossMode} {!isOo ? (
onChange={(e) => { <div className="field">
const mode = <label htmlFor="riskLossMode"></label>
e.target.value === "absolute" <select
? "absolute" id="riskLossMode"
: "percent"; className="mono"
setRiskLossMode(mode); value={riskLossMode}
if (mode !== "percent") setMartingaleOn(false); onChange={(e) => {
}} const mode =
> e.target.value === "absolute"
<option value="percent"> %</option> ? "absolute"
<option value="absolute">USDT</option> : "percent";
</select> setRiskLossMode(mode);
</div> if (mode !== "percent") setMartingaleOn(false);
{riskLossMode === "percent" ? ( }}
>
<option value="percent">
%
</option>
<option value="absolute">USDT</option>
</select>
</div>
) : null}
{isOo || riskLossMode === "percent" ? (
<> <>
<div className="field"> <div className="field">
<label htmlFor="riskCapSrc"></label> <label htmlFor="riskCapSrc"></label>
@@ -1072,10 +1047,18 @@ export default function SettingsPage() {
: mg != null && mg.enabled === true : mg != null && mg.enabled === true
? ` · 倍投待命(连亏${Number(mg.loss_days) || 0}天)` ? ` · 倍投待命(连亏${Number(mg.loss_days) || 0}天)`
: ""; : "";
return `k=${pk ?? "—"} · 预算=${budS}U · 估亏=${mxS}U · 永续=${perp ?? "—"} · 期权=${opt ?? "—"} · 出场=${exit ?? "—"}${basisS}${mgS}`; return isOo
? `预算=${budS}U · 估亏=${mxS}U · 出场=预算×${ooRewardRatio}${
riskPreview.option_qty_eth != null
? ` · 单腿≈${riskPreview.option_qty_eth}ETH`
: ""
}${mgS}`
: `k=${pk ?? "—"} · 预算=${budS}U · 估亏=${mxS}U · 永续=${perp ?? "—"} · 期权=${opt ?? "—"} · 出场=${exit ?? "—"}${basisS}${mgS}`;
})()} })()}
</div> </div>
</div> </div>
{!isOo ? (
<>
<div className="field"> <div className="field">
<label htmlFor="riskPerpU">k=1</label> <label htmlFor="riskPerpU">k=1</label>
<input <input
@@ -1172,8 +1155,12 @@ export default function SettingsPage() {
}} }}
/> />
</div> </div>
</>
) : null}
</> </>
) : null} ) : null}
{!isOo ? (
<>
<div className="field"> <div className="field">
<label htmlFor="perp"> <label htmlFor="perp">
ETH ETH
@@ -1220,6 +1207,8 @@ export default function SettingsPage() {
onChange={(e) => setOptQty(Number(e.target.value))} onChange={(e) => setOptQty(Number(e.target.value))}
/> />
</div> </div>
</>
) : null}
</div> </div>
</section> </section>
) : null} ) : null}
@@ -1228,6 +1217,66 @@ export default function SettingsPage() {
<section className="settings-section"> <section className="settings-section">
<h3></h3> <h3></h3>
<div className="settings-fields"> <div className="settings-fields">
{isOo ? (
<>
<div className="field">
<label htmlFor="ooAmp">%</label>
<input
id="ooAmp"
className="mono"
type="number"
step="0.1"
min="0.1"
value={ooAmpPct}
onChange={(e) => setOoAmpPct(Number(e.target.value))}
/>
</div>
<div className="field">
<label htmlFor="ooAmpH"></label>
<input
id="ooAmpH"
className="mono"
type="number"
step="1"
min="1"
value={ooAmpHours}
onChange={(e) =>
setOoAmpHours(Number(e.target.value))
}
/>
</div>
<div className="field">
<label htmlFor="ooMinH"></label>
<input
id="ooMinH"
className="mono"
type="number"
step="1"
min="1"
value={ooMinHours}
onChange={(e) =>
setOoMinHours(Number(e.target.value))
}
/>
</div>
<div className="field">
<label htmlFor="ooLev"></label>
<input
id="ooLev"
className="mono"
type="number"
step="1"
min="1"
value={ooMinLev}
onChange={(e) => setOoMinLev(Number(e.target.value))}
/>
<p className="hint" style={{ margin: "0.35rem 0 0" }}>
Call Put 使 ATM/
</p>
</div>
</>
) : (
<>
<div className="field"> <div className="field">
<label htmlFor="hours"></label> <label htmlFor="hours"></label>
<input <input
@@ -1309,6 +1358,8 @@ export default function SettingsPage() {
onChange={(e) => setMaxAtmOff(Number(e.target.value))} onChange={(e) => setMaxAtmOff(Number(e.target.value))}
/> />
</div> </div>
</>
)}
</div> </div>
</section> </section>
) : null} ) : null}
@@ -1317,6 +1368,26 @@ export default function SettingsPage() {
<section className="settings-section"> <section className="settings-section">
<h3></h3> <h3></h3>
<div className="settings-fields"> <div className="settings-fields">
{isOo ? (
<div className="field">
<label htmlFor="ooRRExit"></label>
<input
id="ooRRExit"
className="mono"
type="number"
step="0.1"
min="0.5"
value={ooRewardRatio}
onChange={(e) =>
setOoRewardRatio(Number(e.target.value))
}
/>
<p className="hint" style={{ margin: "0.35rem 0 0" }}>
×
</p>
</div>
) : (
<>
<div className="field"> <div className="field">
<label htmlFor="exitMode"></label> <label htmlFor="exitMode"></label>
<select <select
@@ -1387,6 +1458,8 @@ export default function SettingsPage() {
onChange={(e) => setPremMult(Number(e.target.value))} onChange={(e) => setPremMult(Number(e.target.value))}
/> />
</div> </div>
)}
</>
)} )}
<div className="field"> <div className="field">
<label htmlFor="closeDev">/%</label> <label htmlFor="closeDev">/%</label>
@@ -1402,7 +1475,9 @@ export default function SettingsPage() {
</div> </div>
<div className="field"> <div className="field">
<label htmlFor="residualPrem"> <label htmlFor="residualPrem">
/ % {isOo
? "亏损腿残留回收:当前权利金 / 初始权利金 ≥(%)"
: "残留期权回收:当前权利金 / 初始权利金 ≥(%)"}
</label> </label>
<input <input
id="residualPrem" id="residualPrem"
@@ -1532,13 +1607,25 @@ export default function SettingsPage() {
10000 10000
</li> </li>
) : null} ) : null}
<li> {isOo ? (
/OKX <li>
/cash + % 1:1 使//k
</li> </li>
) : (
<li>
/OKX
/cash
</li>
)}
</> </>
) : null} ) : null}
{stratSub === "select" ? ( {stratSub === "select" ? (
isOo ? (
<li>
Call
Put
</li>
) : (
<> <>
<li> <li>
Put Put
@@ -1552,6 +1639,7 @@ export default function SettingsPage() {
ATM ATM
</li> </li>
</> </>
)
) : null} ) : null}
{stratSub === "exit" ? ( {stratSub === "exit" ? (
<> <>
@@ -1560,8 +1648,9 @@ export default function SettingsPage() {
LIVE LIVE
</li> </li>
<li> <li>
{isOo
IOC 20% ? "残留回收:达标只平盈利腿后,亏损腿权利金回升到初始比例及以上时可尝试平仓;否则到期结算。"
: "残留期权回收比例:只平永续后,当买一权利金回升到初始权利金的该比例及以上时,按最新买一 IOC 限价卖掉归档期权(不扫市价);默认 20%。未达标或未完全成交则等到下次巡检或到期结算。"}
</li> </li>
</> </>
) : null} ) : null}