{mode !== "LIVE" ? (
setInitialEquity(Number(e.target.value))
}
/>
) : null}
{!isOo ? (
<>
setLeverage(Number(e.target.value))}
/>
>
) : null}
二选一。期期:近 N 小时振幅高低匹配虚值 Call/Put;达标只平盈利腿。
{isOo ? (
) : null}
{!isOo ? (
) : (
以损定仓(期期固定 · Call/Put 1:1)
)}
{sizingMode === "risk_based" || isOo ? (
<>
{!isOo ? (
选约杠杆:按「指数÷期权杠杆≥」估权利金算
k,权利金再便宜也不放大仓位。
实际杠杆:按盘口卖一定仓,便宜时 k 会变大。
) : null}
{!isOo ? (
) : null}
{isOo || riskLossMode === "percent" ? (
<>
{riskCapitalSource === "manual" ? (
setRiskManualCapital(Number(e.target.value))
}
/>
) : null}
{
const v = Number(e.target.value);
setRiskLossPct(v);
if (v > 3) setMartingaleOn(false);
}}
/>
{riskLossPct > 3
? "亏损幅度超过 3% 时不可启用倍投。"
: "连续亏损日达阈值后翻倍。到期结算无论盈亏(含小盈利)都按亏损日计;达标平仓盈利才打断连亏。"}
{martingaleOn && riskLossPct <= 3 ? (
<>
setMartingaleStartAfter(
Number(e.target.value),
)
}
/>
>
) : null}
>
) : (
setRiskLossUsdt(Number(e.target.value))
}
/>
)}
{(() => {
if (riskPreview == null) return "—";
if (riskPreview.ok === false) {
return String(riskPreview.detail || "预览不可用");
}
const k = Number(riskPreview.k);
const bud = Number(riskPreview.budget);
const mx = Number(riskPreview.max_loss);
const pk = Number.isFinite(k) ? k : null;
const perp =
pk != null
? Number((riskPerpUnit * pk).toFixed(4))
: riskPreview.perp_qty_eth;
const opt =
pk != null
? Number((riskOptUnit * pk).toFixed(4))
: riskPreview.option_qty_eth;
const exit =
pk != null
? Number((riskExitUnit * pk).toFixed(2))
: riskPreview.net_profit_target;
const budS = Number.isFinite(bud)
? bud.toFixed(2)
: "—";
const mxS = Number.isFinite(mx) ? mx.toFixed(2) : "—";
const basis =
riskPreview.leverage_basis === "actual"
? "实际杠杆"
: riskPreview.leverage_basis === "selection"
? "选约杠杆"
: "";
const basisS = basis ? ` · ${basis}` : "";
const mg =
riskPreview.martingale &&
typeof riskPreview.martingale === "object"
? (riskPreview.martingale as Record<
string,
unknown
>)
: null;
const mgD = Number(mg?.doubles);
const mgS =
mg != null &&
mg.enabled === true &&
Number.isFinite(mgD) &&
mgD > 0
? ` · 倍投×${2 ** mgD}(连亏${Number(mg.loss_days) || 0}天·有效${Number(mg.effective_pct)}%)`
: mg != null && mg.enabled === true
? ` · 倍投待命(连亏${Number(mg.loss_days) || 0}天)`
: "";
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}`;
})()}
{!isOo ? (
<>
{
const v = Number(e.target.value);
setRiskPerpUnit(v);
const k = Number(riskPreview?.k);
if (Number.isFinite(k) && k > 0) {
setPerpQty(Number((v * k).toFixed(4)));
}
}}
/>
{
const v = Number(e.target.value);
setRiskOptUnit(v);
const k = Number(riskPreview?.k);
if (Number.isFinite(k) && k > 0) {
setOptQty(Number((v * k).toFixed(4)));
}
}}
/>
{
const v = Number(e.target.value);
setRiskExitUnit(v);
const k = Number(riskPreview?.k);
if (Number.isFinite(k) && k > 0) {
setNetTarget(Number((v * k).toFixed(2)));
setPerpQty(Number((riskPerpUnit * k).toFixed(4)));
setOptQty(Number((riskOptUnit * k).toFixed(4)));
}
}}
/>
{
const k = Number(riskPreview?.k);
if (Number.isFinite(k) && k > 0) {
return Number((riskExitUnit * k).toFixed(2));
}
return Number(riskExitUnit.toFixed(2));
})()
}
onChange={(e) => {
const abs = Number(e.target.value);
const k = Number(riskPreview?.k);
if (Number.isFinite(k) && k > 0) {
const unit = Number((abs / k).toFixed(4));
setRiskExitUnit(unit);
setNetTarget(Number(abs.toFixed(2)));
setPerpQty(Number((riskPerpUnit * k).toFixed(4)));
setOptQty(Number((riskOptUnit * k).toFixed(4)));
} else {
setRiskExitUnit(abs);
setNetTarget(abs);
}
}}
/>
>
) : null}
>
) : null}
{!isOo ? (
<>
0
? Number(
(riskPerpUnit * Number(riskPreview?.k)).toFixed(4),
)
: perpQty
}
onChange={(e) => setPerpQty(Number(e.target.value))}
/>
0
? Number(
(riskOptUnit * Number(riskPreview?.k)).toFixed(4),
)
: optQty
}
onChange={(e) => setOptQty(Number(e.target.value))}
/>
>
) : null}