refactor(hedge): env-driven option-primary UI with grouped params
Move mode switch to HEDGE_PLAN_OPTION_PRIMARY, split left into capital/select/exit groups, and show perp quote above options with leverage auto-match. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -141,6 +141,8 @@ HEDGE_PLAN_ENABLED=false
|
||||
HEDGE_PLAN_SHOW_PERP_OPTIONS=true
|
||||
HEDGE_PLAN_SHOW_OPTIONS_OPTIONS=true
|
||||
HEDGE_PLAN_LIVE_ORDER=false
|
||||
# 永期子模式:true=以期权为主;false=保险模式(页面标题前标识,不可页内切换)
|
||||
HEDGE_PLAN_OPTION_PRIMARY=true
|
||||
HEDGE_PLAN_OPEN_ORDER=options_first
|
||||
HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS=true
|
||||
HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS=false
|
||||
|
||||
@@ -6870,6 +6870,8 @@ def render_main_page(page="trade", embed_mode=None):
|
||||
hedge_plan_show_options_options=_okx_trade_mode == "options_options",
|
||||
hedge_plan_oo_close_mode_enabled=os.getenv("HEDGE_PLAN_OO_CLOSE_MODE_ENABLED", "true").lower()
|
||||
in ("1", "true", "yes", "on"),
|
||||
hedge_plan_option_primary=os.getenv("HEDGE_PLAN_OPTION_PRIMARY", "true").lower()
|
||||
in ("1", "true", "yes", "on"),
|
||||
hedge_plan_budget_buffer=float(os.getenv("HEDGE_PLAN_BUDGET_BUFFER") or "0.95"),
|
||||
options_trade_budget=OKX_OPTIONS_TRADE_BUDGET_USDC,
|
||||
options_budget_buffer=float(os.getenv("OKX_OPTIONS_BUDGET_BUFFER") or "0.95"),
|
||||
|
||||
+6
-4
@@ -1,14 +1,16 @@
|
||||
# 对冲计划 · 永期「以期权为主」
|
||||
|
||||
> 实现日:2026-08-09 · 在现有永期**保险模式**上增加计划级开关,不新增 `OKX_TRADE_MODE`。
|
||||
> 实现日:2026-08-09 · 在现有永期**保险模式**上增加子模式,不新增 `OKX_TRADE_MODE`。
|
||||
> 模式由 env `HEDGE_PLAN_OPTION_PRIMARY` 切换(默认 `true`),页面标题前显示标识,不可在页内切换。
|
||||
|
||||
## 1. 模式对照
|
||||
|
||||
| | 保险模式(开关关) | 以期权为主(开关开) |
|
||||
| | 保险模式(`OPTION_PRIMARY=false`) | 以期权为主(`true`) |
|
||||
|--|------------------|-------------------|
|
||||
| UI 做多 | 永续多 + 买 Put | 买 Call + 永续空 |
|
||||
| UI 做空 | 永续空 + 买 Call | 买 Put + 永续多 |
|
||||
| 左卡 | 开仓价 / 张数 / TP / SL | 权利金 / 杠杆 / 比例 / 到期h / 间隔 / 目标点数 |
|
||||
| 左卡 | 开仓价 / 张数 / TP / SL | 资金与杠杆 / 选约条件 / 出场条件 三组 |
|
||||
| 右卡 | 上永续行情 · 下期权链 | 同上;期权表含杠杆(指数÷卖一),按类型自动匹配 |
|
||||
| 选约 | 仅实值/平值 | 实/平/虚 + 间隔 + 杠杆门 |
|
||||
| 开仓 | 受 `HEDGE_PLAN_OPEN_ORDER` | **强制先期权**,成交后**立即市价**开永续(**不挂**交易所 TP/SL) |
|
||||
| 出场 | 交易所 TP/SL | 相对 K 的点数目标分叉 |
|
||||
@@ -60,7 +62,7 @@ contracts = perp_eth / contract_size
|
||||
| `hedge_plan_orders_lib.py` | 路径、开平永续、启动前定仓刷新 |
|
||||
| `hedge_plan_monitor_lib.py` | `_tick_po_option_primary*` |
|
||||
| `hedge_plan_register.py` / `hedge_plan_db.py` | preview/start/persist;`options-chain?option_primary&min_hours&strike_interval` |
|
||||
| `hedge_plan.js` + `hedge_plan_panel.html` | 开关与左右卡 |
|
||||
| `hedge_plan.js` + `hedge_plan_panel.html` | env 模式标识、左三组参数、右上永续/右下期权 |
|
||||
|
||||
## 6. 测试
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
ooCloseModeEnabled: root.getAttribute("data-oo-close-mode-enabled") !== "0",
|
||||
ooCloseMode: "close_all",
|
||||
direction: "long",
|
||||
optionPrimary: true,
|
||||
optionPrimary: root.getAttribute("data-option-primary") !== "0",
|
||||
opLevTouched: false,
|
||||
opRatioTouched: false,
|
||||
tradingUsdc: null,
|
||||
@@ -283,14 +283,9 @@
|
||||
|
||||
function syncOptionPrimaryUI() {
|
||||
const on = isOptionPrimary();
|
||||
document.querySelectorAll(".hp-po-mode").forEach(function (b) {
|
||||
const v = b.getAttribute("data-option-primary") === "1";
|
||||
b.classList.toggle("is-selected", v === on);
|
||||
b.classList.toggle("active", v === on);
|
||||
});
|
||||
const ins = $("hp-po-fields-insurance");
|
||||
const op = $("hp-po-fields-option-primary");
|
||||
// 保险模式只显示开仓价/张数/止盈止损;以期权为主只显示权利金等执行参数
|
||||
// 保险模式只显示开仓价/张数/止盈止损;以期权为主显示三组参数(env 切换,页内不可改)
|
||||
if (ins) {
|
||||
ins.classList.toggle("hidden", on);
|
||||
if (on) ins.setAttribute("hidden", "hidden");
|
||||
@@ -303,48 +298,39 @@
|
||||
else op.removeAttribute("hidden");
|
||||
op.style.display = on ? "" : "none";
|
||||
}
|
||||
const otmBtn = document.querySelector(".hp-money-otm");
|
||||
if (otmBtn) {
|
||||
const insMoney = $("hp-po-ins-money");
|
||||
if (insMoney) {
|
||||
if (on) {
|
||||
insMoney.setAttribute("hidden", "hidden");
|
||||
insMoney.classList.add("hidden");
|
||||
} else {
|
||||
insMoney.removeAttribute("hidden");
|
||||
insMoney.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
document.querySelectorAll(".hp-money-otm").forEach(function (otmBtn) {
|
||||
otmBtn.classList.toggle("hidden", !on);
|
||||
if (!on) otmBtn.setAttribute("hidden", "hidden");
|
||||
else otmBtn.removeAttribute("hidden");
|
||||
}
|
||||
});
|
||||
if (!on && state.moneyFilter === "otm") {
|
||||
state.moneyFilter = "itm";
|
||||
syncMoneyUI();
|
||||
}
|
||||
if (on) applyOpDefaultsFromMoney(false);
|
||||
const title = $("hp-po-card-title");
|
||||
if (title) title.textContent = on ? "执行参数" : "永续";
|
||||
const rightQ = $("hp-po-perp-quote-right");
|
||||
if (rightQ) {
|
||||
rightQ.classList.toggle("hidden", !on);
|
||||
if (!on) rightQ.setAttribute("hidden", "hidden");
|
||||
else rightQ.removeAttribute("hidden");
|
||||
const badge = $("hp-po-mode-badge");
|
||||
if (badge) {
|
||||
badge.textContent = on ? "以期权为主" : "保险模式";
|
||||
badge.classList.toggle("is-insurance", !on);
|
||||
}
|
||||
const title = $("hp-po-card-title");
|
||||
if (title) title.textContent = "执行参数";
|
||||
const dirLong = document.querySelector('.hp-po-dir[data-dir="long"]');
|
||||
const dirShort = document.querySelector('.hp-po-dir[data-dir="short"]');
|
||||
if (dirLong) dirLong.title = on ? "做多=买Call+永续空" : "做多永续";
|
||||
if (dirShort) dirShort.title = on ? "做空=买Put+永续多" : "做空永续";
|
||||
}
|
||||
|
||||
function setOptionPrimary(on, forceReload) {
|
||||
const next = !!on;
|
||||
const changed = next !== isOptionPrimary();
|
||||
state.optionPrimary = next;
|
||||
if (changed) {
|
||||
state.opLevTouched = false;
|
||||
state.opRatioTouched = false;
|
||||
state.selected = null;
|
||||
if ($("hp-sel-inst")) $("hp-sel-inst").textContent = "—";
|
||||
}
|
||||
syncOptionPrimaryUI();
|
||||
if (!changed && !forceReload) return;
|
||||
void loadMarket().then(function () {
|
||||
return loadChain();
|
||||
});
|
||||
}
|
||||
|
||||
function hoursFromExpMs(expMs) {
|
||||
const n = Number(expMs);
|
||||
if (!n || Number.isNaN(n)) return null;
|
||||
@@ -440,6 +426,37 @@
|
||||
return (Math.round((k / a) * 10) / 10).toFixed(1) + "×";
|
||||
}
|
||||
|
||||
/** 永期期权行情杠杆:指数÷卖一(与选约杠杆门一致). */
|
||||
function calcIndexAskLeverage(ask) {
|
||||
const idx = indexPx();
|
||||
const a = Number(ask);
|
||||
if (!(idx > 0) || !(a > 0)) return "—";
|
||||
return (Math.round((idx / a) * 10) / 10).toFixed(1) + "×";
|
||||
}
|
||||
|
||||
function clearPoSelection() {
|
||||
state.selected = null;
|
||||
if ($("hp-sel-inst")) $("hp-sel-inst").textContent = "—";
|
||||
updatePremiumLine();
|
||||
updatePerpPnlHint();
|
||||
}
|
||||
|
||||
/** 以期权为主:按类型/间隔/杠杆自动匹配最近合约. */
|
||||
function autoMatchPoOption(force) {
|
||||
if (!isOptionPrimary()) return;
|
||||
const want = optTypeForDirection(getDirection());
|
||||
const sel = state.selected;
|
||||
const stillOk =
|
||||
!force &&
|
||||
sel &&
|
||||
String(sel.opt_type || "").toUpperCase() === want &&
|
||||
matchesMoneyFilter(sel);
|
||||
if (stillOk) return;
|
||||
const c = pickClosestItmAtm(currentContracts("hp-exp-select"), want);
|
||||
if (c) pickContract(c);
|
||||
else clearPoSelection();
|
||||
}
|
||||
|
||||
function findAtmStrikeFromRows(rows, idx) {
|
||||
if (!rows.length) return null;
|
||||
if (idx == null || Number.isNaN(Number(idx))) return rows[0].strike;
|
||||
@@ -913,10 +930,6 @@
|
||||
: "");
|
||||
const q = $("hp-perp-quote");
|
||||
if (q) q.innerHTML = quoteHtml;
|
||||
const rightQ = $("hp-po-perp-quote-right");
|
||||
if (rightQ && isOptionPrimary()) {
|
||||
rightQ.innerHTML = "永续行情 · " + quoteHtml;
|
||||
}
|
||||
const contractsInput = $("hp-contracts");
|
||||
if (contractsInput) {
|
||||
const step = amtPrec <= 0 ? "1" : String(Math.pow(10, -amtPrec));
|
||||
@@ -1130,7 +1143,8 @@
|
||||
const prevInst = state.selected && state.selected.inst_id;
|
||||
tbody.innerHTML = "";
|
||||
if (!exp) {
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="muted">请选择到期日</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="muted">请选择到期日</td></tr>';
|
||||
if (isOptionPrimary()) clearPoSelection();
|
||||
return;
|
||||
}
|
||||
const sameType = (exp.contracts || []).filter(function (c) {
|
||||
@@ -1158,7 +1172,8 @@
|
||||
(idx ? " · 指数 " + fmt(idx, 2) : "") +
|
||||
" · 可换到期或点刷新链";
|
||||
}
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="muted">' + hint + "</td></tr>";
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="muted">' + hint + "</td></tr>";
|
||||
if (isOptionPrimary()) clearPoSelection();
|
||||
return;
|
||||
}
|
||||
list.forEach(function (c) {
|
||||
@@ -1171,6 +1186,8 @@
|
||||
c.strike +
|
||||
"</td><td>" +
|
||||
moneynessBadge(c) +
|
||||
'</td><td class="opt-chain-lev" title="指数÷卖一">' +
|
||||
calcIndexAskLeverage(c.ask) +
|
||||
'</td><td class="opt-px-sz">' +
|
||||
fmtPxSz(c.ask, c.ask_sz, c.ask_estimated, c.tick_sz) +
|
||||
'</td><td class="opt-px-sz">' +
|
||||
@@ -1191,6 +1208,7 @@
|
||||
pickContract(c);
|
||||
});
|
||||
});
|
||||
autoMatchPoOption(false);
|
||||
}
|
||||
|
||||
function updatePremiumLine() {
|
||||
@@ -1729,7 +1747,7 @@
|
||||
b.addEventListener("click", function () {
|
||||
const m = b.getAttribute("data-money") || "itm";
|
||||
if (m === "otm" && !isOptionPrimary()) {
|
||||
alert("永期保险腿仅允许实值或平值;请先打开「以期权为主」");
|
||||
alert("永期保险腿仅允许实值或平值;请在 env 将 HEDGE_PLAN_OPTION_PRIMARY=true");
|
||||
return;
|
||||
}
|
||||
state.moneyFilter = m === "otm" ? "otm" : m === "atm" ? "atm" : "itm";
|
||||
@@ -1738,11 +1756,6 @@
|
||||
renderListStrikes();
|
||||
});
|
||||
});
|
||||
document.querySelectorAll(".hp-po-mode").forEach(function (b) {
|
||||
b.addEventListener("click", function () {
|
||||
setOptionPrimary(b.getAttribute("data-option-primary") === "1", true);
|
||||
});
|
||||
});
|
||||
if ($("hp-opt-leverage")) {
|
||||
$("hp-opt-leverage").addEventListener("input", function () {
|
||||
state.opLevTouched = true;
|
||||
@@ -1789,6 +1802,13 @@
|
||||
});
|
||||
if ($("hp-recommend-opt")) {
|
||||
$("hp-recommend-opt").addEventListener("click", function () {
|
||||
if (isOptionPrimary()) {
|
||||
autoMatchPoOption(true);
|
||||
if (!state.selected) {
|
||||
alert("当前选约条件下无匹配合约,请调整类型/间隔/杠杆或换到期");
|
||||
}
|
||||
return;
|
||||
}
|
||||
const want = optTypeForDirection(getDirection());
|
||||
const c = pickClosestItmAtm(currentContracts("hp-exp-select"), want);
|
||||
if (!c) {
|
||||
|
||||
@@ -3470,6 +3470,34 @@ html[data-theme="light"] .opt-be-dist-down {
|
||||
font-size: 0.74rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-mode-badge {
|
||||
display: inline-block;
|
||||
margin-right: 6px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
color: #c4b5fd;
|
||||
background: rgba(139, 92, 246, 0.22);
|
||||
border: 1px solid rgba(167, 139, 250, 0.35);
|
||||
vertical-align: middle;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-mode-badge.is-insurance {
|
||||
color: #93c5fd;
|
||||
background: rgba(59, 130, 246, 0.18);
|
||||
border-color: rgba(96, 165, 250, 0.35);
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-section {
|
||||
margin: 8px 0 10px;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-section-title {
|
||||
margin: 0 0 6px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 650;
|
||||
color: #c5cdd9;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-fields {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
@@ -3480,11 +3508,53 @@ html[data-theme="light"] .opt-be-dist-down {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-fields--section {
|
||||
margin: 0;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-field--type {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-type-seg {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-right-stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-quote-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-ins-money {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-ins-money[hidden],
|
||||
.hedge-plan-page-wrap .hp-po-ins-money.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
/* display:grid 会盖掉 [hidden];模式切换必须显式 none */
|
||||
.hedge-plan-page-wrap .hp-po-fields.hidden,
|
||||
.hedge-plan-page-wrap .hp-po-fields[hidden] {
|
||||
.hedge-plan-page-wrap .hp-po-fields[hidden],
|
||||
.hedge-plan-page-wrap #hp-po-fields-option-primary.hidden,
|
||||
.hedge-plan-page-wrap #hp-po-fields-option-primary[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-strike-table-wrap--6 {
|
||||
max-height: 280px;
|
||||
min-height: 200px;
|
||||
overflow-y: auto;
|
||||
margin-top: 4px;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -3731,6 +3801,7 @@ html[data-theme="light"] .opt-be-dist-down {
|
||||
margin-top: 4px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.hedge-plan-page-wrap .opt-chain-lev,
|
||||
.hedge-plan-page-wrap .hp-oo-table-wrap .opt-chain-lev {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
@@ -3747,12 +3818,20 @@ html[data-theme="light"] .opt-be-dist-down {
|
||||
align-items: stretch;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.hedge-plan-page-wrap .options-dual-grid > .card {
|
||||
.hedge-plan-page-wrap .options-dual-grid > .card,
|
||||
.hedge-plan-page-wrap .hp-po-right-stack > .card {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-right-stack > .hp-po-perp-quote-card {
|
||||
height: auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-po-right-stack > .hp-opt-card {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.hedge-plan-page-wrap .hp-action-row {
|
||||
margin-top: 10px;
|
||||
gap: 8px;
|
||||
|
||||
Vendored
+5
@@ -96,6 +96,7 @@ HOT_RELOAD_EXACT = frozenset({
|
||||
"OKX_TRADE_MODE",
|
||||
"MAX_ACTIVE_HEDGE_PLANS",
|
||||
"HEDGE_PLAN_LIVE_ORDER",
|
||||
"HEDGE_PLAN_OPTION_PRIMARY",
|
||||
"HEDGE_PLAN_OPEN_ORDER",
|
||||
"HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS",
|
||||
"HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS",
|
||||
@@ -154,6 +155,10 @@ SELECT_OPTIONS: dict[str, tuple[tuple[str, str], ...]] = {
|
||||
("perp_options", "永期对冲"),
|
||||
("options_options", "期期对冲"),
|
||||
),
|
||||
"HEDGE_PLAN_OPTION_PRIMARY": (
|
||||
("true", "以期权为主"),
|
||||
("false", "保险模式"),
|
||||
),
|
||||
}
|
||||
|
||||
_SELECT_ALIASES: dict[str, dict[str, str]] = {
|
||||
|
||||
Vendored
+6
@@ -186,6 +186,11 @@ _HEDGE_COMMON_FIELDS: list[tuple[str, str, str]] = [
|
||||
]
|
||||
|
||||
_HEDGE_PO_FIELDS: list[tuple[str, str, str]] = [
|
||||
(
|
||||
"HEDGE_PLAN_OPTION_PRIMARY",
|
||||
"永期模式(以期权为主/保险)",
|
||||
"默认 true=以期权为主;false=保险模式;页面标题前显示标识,不可在页内切换",
|
||||
),
|
||||
("HEDGE_PLAN_OPEN_ORDER", "永期开仓顺序", "options_first 或 perp_first"),
|
||||
("HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS", "永期止损后强制平期权", "保护机制,建议保持 true"),
|
||||
("HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS", "永期止盈后强制平期权", "默认 false,保险腿不平"),
|
||||
@@ -263,6 +268,7 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = {
|
||||
"HEDGE_PLAN_OO_BIAS_SPLIT_BY": "budget",
|
||||
"HEDGE_PLAN_OO_BIAS_RATIO": "0.7",
|
||||
"HEDGE_PLAN_BUDGET_BUFFER": "0.95",
|
||||
"HEDGE_PLAN_OPTION_PRIMARY": "true",
|
||||
"HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE": "true",
|
||||
"HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL": "true",
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
data-show-perp="{{ '1' if hedge_plan_show_perp_options else '0' }}"
|
||||
data-show-oo="{{ '1' if hedge_plan_show_options_options else '0' }}"
|
||||
data-oo-close-mode-enabled="{{ '1' if hedge_plan_oo_close_mode_enabled else '0' }}"
|
||||
data-option-primary="{{ '1' if hedge_plan_option_primary|default(true) else '0' }}"
|
||||
data-budget-buffer="{{ hedge_plan_budget_buffer | default(0.95) }}"
|
||||
data-sizing-mode="{{ position_sizing_mode | default('risk') }}"
|
||||
data-is-full-margin="{{ '1' if position_sizing_mode == 'full_margin' else '0' }}">
|
||||
@@ -43,31 +44,31 @@
|
||||
<div id="hp-tab-perp_options" class="hp-tab-panel" role="tabpanel">
|
||||
<div class="options-dual-grid" id="hp-po-layout">
|
||||
<div class="card hp-po-perp-card">
|
||||
<h2><span id="hp-po-card-title">执行参数</span> · <span id="hp-perp-uly-label">ETH</span> <span class="muted hp-acct-tag" id="hp-perp-acct-tag">合约账户</span></h2>
|
||||
<h2>
|
||||
<span id="hp-po-mode-badge" class="hp-po-mode-badge">以期权为主</span>
|
||||
<span id="hp-po-card-title">执行参数</span>
|
||||
· <span id="hp-perp-uly-label">ETH</span>
|
||||
<span class="muted hp-acct-tag" id="hp-perp-acct-tag">合约账户</span>
|
||||
</h2>
|
||||
<details class="tip-collapse hp-rule-collapse">
|
||||
<summary class="tip-collapse-summary">规则说明</summary>
|
||||
<div class="tip-collapse-body rule-tip">
|
||||
<p><strong>账户</strong>:永续腿走<strong>合约账户</strong>(USDT);期权腿走<strong>期权账户</strong>(USDC)。两账户分开下单、资金不互通。</p>
|
||||
<p><strong>保险模式</strong>(开关关):做多配 Put、做空配 Call;左填开仓/止盈止损;仅实值/平值;交易所 TP/SL 出场。</p>
|
||||
<p><strong>以期权为主</strong>(开关开):做多买 Call+永续空、做空买 Put+永续多;左填权利金/杠杆/比例/目标点数;开仓先期权后市价永续;期权目标验买一且净利>0后双平;永续目标只平永续、期权持有至到期。</p>
|
||||
<p><strong>模式</strong>:在 env <code>HEDGE_PLAN_OPTION_PRIMARY</code> 切换(true=以期权为主 / false=保险模式);标题前标识当前模式。</p>
|
||||
<p><strong>保险模式</strong>:做多配 Put、做空配 Call;左填开仓/止盈止损;仅实值/平值;交易所 TP/SL 出场。</p>
|
||||
<p><strong>以期权为主</strong>:做多买 Call+永续空、做空买 Put+永续多;左分资金/选约/出场三组;右侧上永续下期权(含杠杆),按类型自动匹配;开仓先期权后市价永续。</p>
|
||||
</div>
|
||||
</details>
|
||||
<div class="form-row hp-uly-row">
|
||||
<button type="button" class="btn-secondary hp-uly-btn active" data-uly="ETH">ETH</button>
|
||||
<button type="button" class="btn-secondary hp-uly-btn" data-uly="BTC">BTC</button>
|
||||
</div>
|
||||
<div class="form-row hp-po-mode-row" role="group" aria-label="永期模式">
|
||||
<button type="button" class="btn-secondary hp-po-mode" data-option-primary="0">保险模式</button>
|
||||
<button type="button" class="btn-secondary hp-po-mode is-selected" data-option-primary="1">以期权为主</button>
|
||||
</div>
|
||||
<div class="hp-po-top">
|
||||
<div class="hp-oo-seg hp-po-dir-seg" role="group" aria-label="方向">
|
||||
<button type="button" class="btn-secondary hp-po-dir is-selected" data-dir="long" title="做多=买Call+永续空"><span class="hp-oo-check" aria-hidden="true">✓</span>做多</button>
|
||||
<button type="button" class="btn-secondary hp-po-dir" data-dir="short" title="做空=买Put+永续多"><span class="hp-oo-check" aria-hidden="true">✓</span>做空</button>
|
||||
</div>
|
||||
<span id="hp-po-mark" class="hp-po-mark" aria-live="polite">标记 —</span>
|
||||
</div>
|
||||
<p id="hp-perp-quote" class="muted hp-po-meta">加载中…</p>
|
||||
<div class="hp-po-fields hidden" id="hp-po-fields-insurance" hidden>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">开仓价 <em>USDT</em></span>
|
||||
@@ -86,81 +87,115 @@
|
||||
<input type="number" step="any" id="hp-sl" placeholder="保护价" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="hp-po-fields" id="hp-po-fields-option-primary">
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">权利金 <em>USDC</em></span>
|
||||
<input type="number" step="any" id="hp-premium-budget" placeholder="预算(执行×0.95)" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">永续杠杆</span>
|
||||
<input type="number" step="1" id="hp-perp-leverage" value="100" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">期权杠杆</span>
|
||||
<input type="number" step="1" id="hp-opt-leverage" value="100" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">期权:永续比例</span>
|
||||
<input type="number" step="any" id="hp-opt-perp-ratio" value="2" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">到期时间 <em>最短h</em></span>
|
||||
<input type="number" step="1" id="hp-min-hours" value="36" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">期权间隔 <em>点</em></span>
|
||||
<input type="number" step="any" id="hp-strike-interval" value="15" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">期权目标位 <em>相对K</em></span>
|
||||
<input type="number" step="any" id="hp-opt-target-pts" placeholder="点数" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">永续目标位 <em>相对K</em></span>
|
||||
<input type="number" step="any" id="hp-perp-target-pts" placeholder="点数" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<div id="hp-po-fields-option-primary">
|
||||
<section class="hp-po-section" aria-labelledby="hp-po-sec-capital">
|
||||
<h3 id="hp-po-sec-capital" class="hp-po-section-title">资金与杠杆配置</h3>
|
||||
<div class="hp-po-fields hp-po-fields--section">
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">权利金 <em>USDC</em></span>
|
||||
<input type="number" step="any" id="hp-premium-budget" placeholder="预算(执行×0.95)" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">永续杠杆</span>
|
||||
<input type="number" step="1" id="hp-perp-leverage" value="100" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">期权杠杆</span>
|
||||
<input type="number" step="1" id="hp-opt-leverage" value="100" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<section class="hp-po-section" aria-labelledby="hp-po-sec-select">
|
||||
<h3 id="hp-po-sec-select" class="hp-po-section-title">选约条件</h3>
|
||||
<div class="hp-po-fields hp-po-fields--section">
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">到期时间 <em>最短h</em></span>
|
||||
<input type="number" step="1" id="hp-min-hours" value="36" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">期权间隔 <em>点</em></span>
|
||||
<input type="number" step="any" id="hp-strike-interval" value="15" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<div class="hp-po-field hp-po-field--type">
|
||||
<span class="hp-po-field-lab">类型</span>
|
||||
<div class="hp-oo-seg hp-po-type-seg" role="group" aria-label="虚实值类型">
|
||||
<button type="button" class="btn-secondary hp-money-btn active" data-money="itm" title="实值+平值"><span class="hp-oo-check" aria-hidden="true">✓</span>实值/平值</button>
|
||||
<button type="button" class="btn-secondary hp-money-btn" data-money="atm" title="仅平值"><span class="hp-oo-check" aria-hidden="true">✓</span>仅平值</button>
|
||||
<button type="button" class="btn-secondary hp-money-btn hp-money-otm" data-money="otm" title="虚值"><span class="hp-oo-check" aria-hidden="true">✓</span>虚值</button>
|
||||
</div>
|
||||
</div>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">比例 <em>期权:永续</em></span>
|
||||
<input type="number" step="any" id="hp-opt-perp-ratio" value="2" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
<section class="hp-po-section" aria-labelledby="hp-po-sec-exit">
|
||||
<h3 id="hp-po-sec-exit" class="hp-po-section-title">出场条件</h3>
|
||||
<div class="hp-po-fields hp-po-fields--section">
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">期权目标位 <em>相对K</em></span>
|
||||
<input type="number" step="any" id="hp-opt-target-pts" placeholder="点数" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
<label class="hp-po-field">
|
||||
<span class="hp-po-field-lab">永续目标位 <em>相对K</em></span>
|
||||
<input type="number" step="any" id="hp-perp-target-pts" placeholder="点数" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="hp-po-summary">
|
||||
<div id="hp-perp-pnl-line" class="hp-po-pnl"></div>
|
||||
<div id="hp-sizing-line" class="muted hp-po-sizing"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card hp-opt-card">
|
||||
<h2>期权 · <span id="hp-opt-type-label">Call</span> <span class="muted hp-acct-tag" id="hp-opt-acct-tag">期权账户</span></h2>
|
||||
<p id="hp-po-perp-quote-right" class="muted hp-po-meta"></p>
|
||||
<div class="form-row hp-opt-toolbar hp-po-opt-toolbar">
|
||||
<select id="hp-exp-select"><option value="">选择到期日</option></select>
|
||||
<button type="button" class="btn-secondary hp-money-btn active" data-money="itm" title="实值+平值">实值/平值</button>
|
||||
<button type="button" class="btn-secondary hp-money-btn" data-money="atm" title="仅平值">仅平值</button>
|
||||
<button type="button" class="btn-secondary hp-money-btn hp-money-otm" data-money="otm" title="虚值">虚值</button>
|
||||
<button type="button" class="btn-secondary" id="hp-recommend-opt" title="推荐选约">推荐</button>
|
||||
<button type="button" class="btn-secondary" id="hp-load-chain">刷新链</button>
|
||||
<span id="hp-index-line" class="hp-po-index" aria-live="polite">指数 —</span>
|
||||
<div class="hp-po-right-stack">
|
||||
<div class="card hp-po-perp-quote-card">
|
||||
<h2>永续行情 <span class="muted hp-acct-tag">合约账户</span></h2>
|
||||
<div class="hp-po-quote-head">
|
||||
<span id="hp-po-mark" class="hp-po-mark" aria-live="polite">标记 —</span>
|
||||
</div>
|
||||
<p id="hp-perp-quote" class="muted hp-po-meta">加载中…</p>
|
||||
<p id="hp-po-perp-quote-right" class="muted hp-po-meta" hidden></p>
|
||||
</div>
|
||||
<div class="options-strike-table-wrap hp-strike-table-wrap--5">
|
||||
<table class="options-strike-table" id="hp-strike-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>行权价</th>
|
||||
<th>实虚值</th>
|
||||
<th>卖一/张</th>
|
||||
<th>买一/张</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="hp-strike-tbody">
|
||||
<tr><td colspan="5" class="muted">请刷新期权链</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="form-row hp-pick-row">
|
||||
<label>已选 <code id="hp-sel-inst">—</code></label>
|
||||
<label>张数 <span class="hp-unit">期权张</span> <input type="number" step="1" min="1" id="hp-sheets" value="1" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" /></label>
|
||||
<span class="muted" id="hp-premium-line"></span>
|
||||
</div>
|
||||
<div id="hp-opt-bal-line" class="muted hp-po-meta hp-opt-bal-line"></div>
|
||||
<div class="form-row hp-action-row">
|
||||
<button type="button" class="primary" id="hp-preview-btn">计算</button>
|
||||
<div class="card hp-opt-card">
|
||||
<h2>期权 · <span id="hp-opt-type-label">Call</span> <span class="muted hp-acct-tag" id="hp-opt-acct-tag">期权账户</span></h2>
|
||||
<div class="form-row hp-opt-toolbar hp-po-opt-toolbar">
|
||||
<select id="hp-exp-select"><option value="">选择到期日</option></select>
|
||||
<span class="hp-po-ins-money" id="hp-po-ins-money" hidden>
|
||||
<button type="button" class="btn-secondary hp-money-btn active" data-money="itm" title="实值+平值">实值/平值</button>
|
||||
<button type="button" class="btn-secondary hp-money-btn" data-money="atm" title="仅平值">仅平值</button>
|
||||
</span>
|
||||
<button type="button" class="btn-secondary" id="hp-recommend-opt" title="按当前类型自动匹配最近合约">自动匹配</button>
|
||||
<button type="button" class="btn-secondary" id="hp-load-chain">刷新链</button>
|
||||
<span id="hp-index-line" class="hp-po-index" aria-live="polite">指数 —</span>
|
||||
</div>
|
||||
<div class="options-strike-table-wrap hp-strike-table-wrap--6">
|
||||
<table class="options-strike-table" id="hp-strike-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>行权价</th>
|
||||
<th>实虚值</th>
|
||||
<th title="指数÷卖一">杠杆</th>
|
||||
<th>卖一/张</th>
|
||||
<th>买一/张</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="hp-strike-tbody">
|
||||
<tr><td colspan="6" class="muted">请刷新期权链</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="form-row hp-pick-row">
|
||||
<label>已选 <code id="hp-sel-inst">—</code></label>
|
||||
<label>张数 <span class="hp-unit">期权张</span> <input type="number" step="1" min="1" id="hp-sheets" value="1" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" /></label>
|
||||
<span class="muted" id="hp-premium-line"></span>
|
||||
</div>
|
||||
<div id="hp-opt-bal-line" class="muted hp-po-meta hp-opt-bal-line"></div>
|
||||
<div class="form-row hp-action-row">
|
||||
<button type="button" class="primary" id="hp-preview-btn">计算</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -368,4 +403,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/hedge_plan.js?v=40"></script>
|
||||
<script src="/static/hedge_plan.js?v=41"></script>
|
||||
|
||||
Reference in New Issue
Block a user