Hide perp signal direction in option-option mode.
Plan panel shows Call+Put structure and OO selection/exit labels instead. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -261,6 +261,36 @@ class StrategyEngine:
|
|||||||
in ("perp_option", "option_option")
|
in ("perp_option", "option_option")
|
||||||
else "perp_option"
|
else "perp_option"
|
||||||
),
|
),
|
||||||
|
"oo_amplitude_pct": float(
|
||||||
|
self.ledger.get_setting_float(
|
||||||
|
"oo_amplitude_pct", s.oo_amplitude_pct
|
||||||
|
)
|
||||||
|
or s.oo_amplitude_pct
|
||||||
|
),
|
||||||
|
"oo_amplitude_hours": float(
|
||||||
|
self.ledger.get_setting_float(
|
||||||
|
"oo_amplitude_hours", s.oo_amplitude_hours
|
||||||
|
)
|
||||||
|
or s.oo_amplitude_hours
|
||||||
|
),
|
||||||
|
"oo_min_option_hours": float(
|
||||||
|
self.ledger.get_setting_float(
|
||||||
|
"oo_min_option_hours", s.oo_min_option_hours
|
||||||
|
)
|
||||||
|
or s.oo_min_option_hours
|
||||||
|
),
|
||||||
|
"oo_min_leverage": float(
|
||||||
|
self.ledger.get_setting_float(
|
||||||
|
"oo_min_leverage", s.oo_min_leverage
|
||||||
|
)
|
||||||
|
or s.oo_min_leverage
|
||||||
|
),
|
||||||
|
"oo_reward_ratio": float(
|
||||||
|
self.ledger.get_setting_float(
|
||||||
|
"oo_reward_ratio", s.oo_reward_ratio
|
||||||
|
)
|
||||||
|
or s.oo_reward_ratio
|
||||||
|
),
|
||||||
"risk_perp_unit": risk_perp_unit,
|
"risk_perp_unit": risk_perp_unit,
|
||||||
"risk_option_unit": risk_option_unit,
|
"risk_option_unit": risk_option_unit,
|
||||||
"risk_exit_unit": risk_exit_unit,
|
"risk_exit_unit": risk_exit_unit,
|
||||||
|
|||||||
@@ -348,6 +348,11 @@ export type PlanState = {
|
|||||||
risk_effective_loss_pct?: number;
|
risk_effective_loss_pct?: number;
|
||||||
risk_loss_pct?: number;
|
risk_loss_pct?: number;
|
||||||
hedge_mode?: "perp_option" | "option_option";
|
hedge_mode?: "perp_option" | "option_option";
|
||||||
|
oo_amplitude_pct?: number;
|
||||||
|
oo_amplitude_hours?: number;
|
||||||
|
oo_min_option_hours?: number;
|
||||||
|
oo_min_leverage?: number;
|
||||||
|
oo_reward_ratio?: number;
|
||||||
sizing_mode?: "manual" | "risk_based";
|
sizing_mode?: "manual" | "risk_based";
|
||||||
risk_based?: boolean;
|
risk_based?: boolean;
|
||||||
ledger: { equity: number; available: number; reserved: number };
|
ledger: { equity: number; available: number; reserved: number };
|
||||||
|
|||||||
+107
-51
@@ -185,6 +185,10 @@ export default function PlanPage() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const pos = plan?.position;
|
const pos = plan?.position;
|
||||||
|
const isOo =
|
||||||
|
plan?.hedge_mode === "option_option" ||
|
||||||
|
pos?.hedge_mode === "option_option" ||
|
||||||
|
!!pos?.option2_inst_id;
|
||||||
const open = !!pos?.has_position;
|
const open = !!pos?.has_position;
|
||||||
const exitMode = plan?.exit_mode ?? "fixed_usdt";
|
const exitMode = plan?.exit_mode ?? "fixed_usdt";
|
||||||
const riskBased =
|
const riskBased =
|
||||||
@@ -202,20 +206,28 @@ export default function PlanPage() {
|
|||||||
: null;
|
: null;
|
||||||
const netPnl = pos?.net_pnl ?? 0;
|
const netPnl = pos?.net_pnl ?? 0;
|
||||||
const movePct = pos?.move_pct ?? 0;
|
const movePct = pos?.move_pct ?? 0;
|
||||||
const exitRuleLabel =
|
const ooRatio = Number(plan?.oo_reward_ratio ?? 2);
|
||||||
exitMode === "premium_multiple"
|
const exitRuleLabel = isOo
|
||||||
|
? exitTarget != null
|
||||||
|
? `${riskLocked ? "锁定 " : ""}净盈≥${fmt(exitTarget)} U(预算×${fmt(ooRatio, 1)})`
|
||||||
|
: `净盈≥预算×${fmt(ooRatio, 1)}(达标只平盈利腿)`
|
||||||
|
: exitMode === "premium_multiple"
|
||||||
? `权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
|
? `权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
|
||||||
: riskBased
|
: riskBased
|
||||||
? exitTarget != null
|
? exitTarget != null
|
||||||
? `${riskLocked ? "锁定 " : "固定 "}${fmt(exitTarget)} U(基数${fmt(plan?.risk_exit_unit ?? 15)})`
|
? `${riskLocked ? "锁定 " : "固定 "}${fmt(exitTarget)} U(基数${fmt(plan?.risk_exit_unit ?? 15)})`
|
||||||
: `待估算(基数${fmt(plan?.risk_exit_unit ?? 15)})`
|
: `待估算(基数${fmt(plan?.risk_exit_unit ?? 15)})`
|
||||||
: `固定 ${fmt(plan?.net_profit_target ?? 15)} U`;
|
: `固定 ${fmt(plan?.net_profit_target ?? 15)} U`;
|
||||||
const riskRatioLabel = `比例${Number(plan?.risk_perp_unit ?? 1)}:${Number(plan?.risk_option_unit ?? 2)}`;
|
const riskRatioLabel = isOo
|
||||||
|
? "Call:Put 1:1"
|
||||||
|
: `比例${Number(plan?.risk_perp_unit ?? 1)}:${Number(plan?.risk_option_unit ?? 2)}`;
|
||||||
const sizingModeLabel = riskBased
|
const sizingModeLabel = riskBased
|
||||||
? [
|
? [
|
||||||
plan?.hedge_mode === "option_option" ? "期期对冲" : "以损定仓",
|
isOo ? "期期对冲" : "以损定仓",
|
||||||
riskRatioLabel,
|
riskRatioLabel,
|
||||||
plan?.risk_last_k != null ? `k=${fmt(plan.risk_last_k, 1)}` : null,
|
!isOo && plan?.risk_last_k != null
|
||||||
|
? `k=${fmt(plan.risk_last_k, 1)}`
|
||||||
|
: null,
|
||||||
riskLocked
|
riskLocked
|
||||||
? exitTarget != null
|
? exitTarget != null
|
||||||
? `目标锁定${fmt(exitTarget, 2)}U`
|
? `目标锁定${fmt(exitTarget, 2)}U`
|
||||||
@@ -236,7 +248,7 @@ export default function PlanPage() {
|
|||||||
]
|
]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(" ")
|
.join(" ")
|
||||||
: plan?.hedge_mode === "option_option"
|
: isOo
|
||||||
? "期期对冲"
|
? "期期对冲"
|
||||||
: "手动仓位";
|
: "手动仓位";
|
||||||
const phaseLabel = PHASE_ZH[plan?.phase || ""] || plan?.phase || "—";
|
const phaseLabel = PHASE_ZH[plan?.phase || ""] || plan?.phase || "—";
|
||||||
@@ -247,8 +259,18 @@ export default function PlanPage() {
|
|||||||
: plan?.atm_open_offset_enabled
|
: plan?.atm_open_offset_enabled
|
||||||
? `ATM偏差≤${fmt(plan?.max_atm_open_offset ?? 3, 0)}`
|
? `ATM偏差≤${fmt(plan?.max_atm_open_offset ?? 3, 0)}`
|
||||||
: "ATM偏差关";
|
: "ATM偏差关";
|
||||||
const exitDetail =
|
const ooSelectLabel = [
|
||||||
exitMode === "premium_multiple"
|
`振幅≥${fmt(plan?.oo_amplitude_pct ?? 1.5, 1)}%/${fmt(plan?.oo_amplitude_hours ?? 12, 0)}h`,
|
||||||
|
"虚值Call@高·Put@低",
|
||||||
|
`剩余≥${fmt(plan?.oo_min_option_hours ?? 24, 0)}h`,
|
||||||
|
`杠杆≥${fmt(plan?.oo_min_leverage ?? 200, 0)}x`,
|
||||||
|
displayOptQty != null ? `单腿${fmt(displayOptQty, 1)}ETH` : null,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" · ");
|
||||||
|
const exitDetail = isOo
|
||||||
|
? `净盈利≥预算×${fmt(ooRatio, 1)} → 只平盈利腿,亏损腿残留`
|
||||||
|
: exitMode === "premium_multiple"
|
||||||
? `净盈利≥初始权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
|
? `净盈利≥初始权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
|
||||||
: `净盈利≥${fmt(plan?.net_profit_target ?? 15)} U`;
|
: `净盈利≥${fmt(plan?.net_profit_target ?? 15)} U`;
|
||||||
const expiryMs =
|
const expiryMs =
|
||||||
@@ -328,26 +350,40 @@ export default function PlanPage() {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span className="plan-rules-k">开仓</span>
|
<span className="plan-rules-k">开仓</span>
|
||||||
永续{" "}
|
{isOo ? (
|
||||||
{displayPerpQty != null
|
<>
|
||||||
? `${fmt(displayPerpQty, 2)} ETH`
|
{ooSelectLabel}
|
||||||
: "—"}{" "}
|
{plan?.skip_weekends ? " · 周末跳过开仓" : ""}
|
||||||
/ {fmt(plan?.leverage, 0)}x
|
{plan?.one_expiry_per_day !== false
|
||||||
· 期权{" "}
|
? " · 每个到期只开一次"
|
||||||
{displayOptQty != null
|
: ""}
|
||||||
? `${fmt(displayOptQty, 2)} ETH`
|
</>
|
||||||
: "—"}{" "}
|
) : (
|
||||||
名义 · 剩余≥
|
<>
|
||||||
{fmt(plan?.min_option_hours, 0)}h · 期权杠杆≥
|
永续{" "}
|
||||||
{fmt(plan?.min_option_leverage, 0)}x · {atmRule}
|
{displayPerpQty != null
|
||||||
{plan?.skip_weekends ? " · 周末跳过开仓" : ""}
|
? `${fmt(displayPerpQty, 2)} ETH`
|
||||||
{plan?.one_expiry_per_day !== false
|
: "—"}{" "}
|
||||||
? " · 每个到期只开一次"
|
/ {fmt(plan?.leverage, 0)}x
|
||||||
: ""}
|
· 期权{" "}
|
||||||
|
{displayOptQty != null
|
||||||
|
? `${fmt(displayOptQty, 2)} ETH`
|
||||||
|
: "—"}{" "}
|
||||||
|
名义 · 剩余≥
|
||||||
|
{fmt(plan?.min_option_hours, 0)}h · 期权杠杆≥
|
||||||
|
{fmt(plan?.min_option_leverage, 0)}x · {atmRule}
|
||||||
|
{plan?.skip_weekends ? " · 周末跳过开仓" : ""}
|
||||||
|
{plan?.one_expiry_per_day !== false
|
||||||
|
? " · 每个到期只开一次"
|
||||||
|
: ""}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span className="plan-rules-k">平仓</span>
|
<span className="plan-rules-k">平仓</span>
|
||||||
{exitDetail} → 双腿全平;期权远虚则只平永续、期权到期结算;未达标拖到期
|
{isOo
|
||||||
|
? `${exitDetail};否则到期结算`
|
||||||
|
: `${exitDetail} → 双腿全平;期权远虚则只平永续、期权到期结算;未达标拖到期`}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span className="plan-rules-k">节奏</span>
|
<span className="plan-rules-k">节奏</span>
|
||||||
@@ -460,24 +496,30 @@ export default function PlanPage() {
|
|||||||
<div className="kv">
|
<div className="kv">
|
||||||
<span>选约条件</span>
|
<span>选约条件</span>
|
||||||
<span className="mono">
|
<span className="mono">
|
||||||
永续
|
{isOo ? (
|
||||||
{displayPerpQty != null
|
ooSelectLabel
|
||||||
? `${fmt(displayPerpQty, 2)}ETH`
|
) : (
|
||||||
: "—"}
|
<>
|
||||||
/期权
|
永续
|
||||||
{displayOptQty != null
|
{displayPerpQty != null
|
||||||
? `${fmt(displayOptQty, 2)}ETH`
|
? `${fmt(displayPerpQty, 2)}ETH`
|
||||||
: "—"}{" "}
|
: "—"}
|
||||||
· 剩余≥
|
/期权
|
||||||
{fmt(plan?.min_option_hours, 0)}h · 期权杠杆≥
|
{displayOptQty != null
|
||||||
{fmt(plan?.min_option_leverage, 0)}x
|
? `${fmt(displayOptQty, 2)}ETH`
|
||||||
{plan?.fixed_direction_enabled
|
: "—"}{" "}
|
||||||
? plan?.fixed_perp_side === "short"
|
· 剩余≥
|
||||||
? " · 固定空+Call(实/平)"
|
{fmt(plan?.min_option_hours, 0)}h · 期权杠杆≥
|
||||||
: " · 固定多+Put(实/平)"
|
{fmt(plan?.min_option_leverage, 0)}x
|
||||||
: plan?.atm_open_offset_enabled
|
{plan?.fixed_direction_enabled
|
||||||
? ` · ATM偏差≤${fmt(plan?.max_atm_open_offset ?? 3, 0)}`
|
? plan?.fixed_perp_side === "short"
|
||||||
: " · ATM偏差关"}
|
? " · 固定空+Call(实/平)"
|
||||||
|
: " · 固定多+Put(实/平)"
|
||||||
|
: plan?.atm_open_offset_enabled
|
||||||
|
? ` · ATM偏差≤${fmt(plan?.max_atm_open_offset ?? 3, 0)}`
|
||||||
|
: " · ATM偏差关"}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="kv">
|
<div className="kv">
|
||||||
@@ -525,10 +567,20 @@ export default function PlanPage() {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="kv">
|
{isOo ? (
|
||||||
<span>信号方向</span>
|
<div className="kv">
|
||||||
<span className="mono">{biasTag}</span>
|
<span>开仓结构</span>
|
||||||
</div>
|
<span className="mono">
|
||||||
|
<span className="tag">买 Call + 买 Put</span>
|
||||||
|
<span className="meta"> · 不按永期方向信号</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="kv">
|
||||||
|
<span>信号方向</span>
|
||||||
|
<span className="mono">{biasTag}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="kv">
|
<div className="kv">
|
||||||
<span>出场规则</span>
|
<span>出场规则</span>
|
||||||
<span className="mono">{exitRuleLabel}</span>
|
<span className="mono">{exitRuleLabel}</span>
|
||||||
@@ -540,7 +592,7 @@ export default function PlanPage() {
|
|||||||
{open ? fmt(netPnl) : "—"}
|
{open ? fmt(netPnl) : "—"}
|
||||||
</span>
|
</span>
|
||||||
{" / "}
|
{" / "}
|
||||||
{open || exitMode === "fixed_usdt"
|
{open || exitMode === "fixed_usdt" || isOo
|
||||||
? exitTarget != null
|
? exitTarget != null
|
||||||
? fmt(exitTarget)
|
? fmt(exitTarget)
|
||||||
: "—"
|
: "—"
|
||||||
@@ -548,11 +600,15 @@ export default function PlanPage() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="kv">
|
<div className="kv">
|
||||||
<span>永续/期权浮盈</span>
|
<span>{isOo ? "Call/Put 浮盈" : "永续/期权浮盈"}</span>
|
||||||
<span className="mono">
|
<span className="mono">
|
||||||
<span className={pnlClass(pos?.perp_upl)}>{fmt(pos?.perp_upl)}</span>
|
<span className={pnlClass(pos?.perp_upl)}>
|
||||||
|
{fmt(isOo ? pos?.option_upl : pos?.perp_upl)}
|
||||||
|
</span>
|
||||||
{" / "}
|
{" / "}
|
||||||
<span className={pnlClass(pos?.option_upl)}>{fmt(pos?.option_upl)}</span>
|
<span className={pnlClass(isOo ? pos?.option2_upl : pos?.option_upl)}>
|
||||||
|
{fmt(isOo ? pos?.option2_upl : pos?.option_upl)}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{plan?.mode === "LIVE" && open ? (
|
{plan?.mode === "LIVE" && open ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user