Swap 永期 layout to left option select / right order; default opt:perp ratio 2.
Call pairs with perp short and Put with perp long; sizing shows coin notional so 1 BTC option hedges 0.5 BTC perp. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+1
-1
@@ -22,7 +22,7 @@
|
|||||||
| 权利金 | 用户填(USDC 预算) |
|
| 权利金 | 用户填(USDC 预算) |
|
||||||
| 永续杠杆 | 100 |
|
| 永续杠杆 | 100 |
|
||||||
| 期权杠杆 | 实/平 100;虚 200 |
|
| 期权杠杆 | 实/平 100;虚 200 |
|
||||||
| 期权:永续比例 | 实/平 2;虚 4 |
|
| 期权:永续比例 | 默认 2(期权名义÷比例=永续名义;例 1 BTC→0.5 BTC) |
|
||||||
| 到期时间(最短 h) | 36 |
|
| 到期时间(最短 h) | 36 |
|
||||||
| 期权间隔(点) | 15 |
|
| 期权间隔(点) | 15 |
|
||||||
| 期权/永续目标位 | 相对 K 点数,须 **>0** |
|
| 期权/永续目标位 | 相对 K 点数,须 **>0** |
|
||||||
|
|||||||
+103
-40
@@ -65,6 +65,18 @@
|
|||||||
b.classList.toggle("is-selected", on);
|
b.classList.toggle("is-selected", on);
|
||||||
b.classList.toggle("active", on);
|
b.classList.toggle("active", on);
|
||||||
});
|
});
|
||||||
|
const hint = $("hp-po-pair-hint");
|
||||||
|
if (hint) {
|
||||||
|
if (isOptionPrimary()) {
|
||||||
|
hint.textContent = dir === "short" ? "买 Put + 永续多" : "买 Call + 永续空";
|
||||||
|
} else {
|
||||||
|
hint.textContent = dir === "short" ? "永续空 + 保险 Call" : "永续多 + 保险 Put";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const typeLab = $("hp-opt-type-label");
|
||||||
|
if (typeLab && isOptionPrimary()) {
|
||||||
|
typeLab.textContent = dir === "short" ? "Put" : "Call";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setDirection(dir, forceReload) {
|
function setDirection(dir, forceReload) {
|
||||||
@@ -282,7 +294,8 @@
|
|||||||
levEl.value = kind === "otm" ? "200" : "100";
|
levEl.value = kind === "otm" ? "200" : "100";
|
||||||
}
|
}
|
||||||
if (ratioEl && (force || !state.opRatioTouched)) {
|
if (ratioEl && (force || !state.opRatioTouched)) {
|
||||||
ratioEl.value = kind === "otm" ? "4" : "2";
|
// 默认 2:期权名义÷比例=永续名义(例 1 BTC 期权 → 0.5 BTC 永续)
|
||||||
|
ratioEl.value = "2";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,11 +326,6 @@
|
|||||||
insMoney.classList.remove("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") {
|
if (!on && state.moneyFilter === "otm") {
|
||||||
state.moneyFilter = "itm";
|
state.moneyFilter = "itm";
|
||||||
syncMoneyUI();
|
syncMoneyUI();
|
||||||
@@ -329,11 +337,26 @@
|
|||||||
badge.classList.toggle("is-insurance", !on);
|
badge.classList.toggle("is-insurance", !on);
|
||||||
}
|
}
|
||||||
const title = $("hp-po-card-title");
|
const title = $("hp-po-card-title");
|
||||||
if (title) title.textContent = "执行参数";
|
if (title) title.textContent = on ? "下单" : "执行参数";
|
||||||
const dirLong = document.querySelector('.hp-po-dir[data-dir="long"]');
|
const dirLong = document.querySelector('.hp-po-dir[data-dir="long"]');
|
||||||
const dirShort = document.querySelector('.hp-po-dir[data-dir="short"]');
|
const dirShort = document.querySelector('.hp-po-dir[data-dir="short"]');
|
||||||
if (dirLong) dirLong.title = on ? "做多=买Call+永续空" : "做多永续";
|
if (dirLong) {
|
||||||
if (dirShort) dirShort.title = on ? "做空=买Put+永续多" : "做空永续";
|
dirLong.title = on ? "买 Call → 永续空" : "做多永续";
|
||||||
|
if (on) {
|
||||||
|
dirLong.innerHTML = '<span class="hp-oo-check" aria-hidden="true">✓</span>Call';
|
||||||
|
} else {
|
||||||
|
dirLong.innerHTML = '<span class="hp-oo-check" aria-hidden="true">✓</span>做多';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dirShort) {
|
||||||
|
dirShort.title = on ? "买 Put → 永续多" : "做空永续";
|
||||||
|
if (on) {
|
||||||
|
dirShort.innerHTML = '<span class="hp-oo-check" aria-hidden="true">✓</span>Put';
|
||||||
|
} else {
|
||||||
|
dirShort.innerHTML = '<span class="hp-oo-check" aria-hidden="true">✓</span>做空';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
syncPoDirUI();
|
||||||
syncPoActionBtn();
|
syncPoActionBtn();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,33 +374,75 @@
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeOpSizing(ask, ctMult) {
|
function computeOpSizing(ask, ctMult, sheetsOverride) {
|
||||||
const budget = numInput("hp-premium-budget", 0);
|
const budget = numInput("hp-premium-budget", 0);
|
||||||
const ratio = numInput("hp-opt-perp-ratio", 2);
|
const ratio = numInput("hp-opt-perp-ratio", 2);
|
||||||
const cs = Number((state.market && state.market.contract_size) || 0.01);
|
const cs = Number((state.market && state.market.contract_size) || 0.01);
|
||||||
const usable = budget * 0.95;
|
const usable = budget * 0.95;
|
||||||
const a = Number(ask || 0);
|
const a = Number(ask || 0);
|
||||||
const ct = Number(ctMult || 0.01);
|
const ct = Number(ctMult || 0.01);
|
||||||
if (!(budget > 0) || !(a > 0) || !(ct > 0) || !(ratio > 0) || !(cs > 0)) {
|
if (!(ct > 0) || !(ratio > 0) || !(cs > 0)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let eth = Math.floor((usable / a) * 100 + 1e-12) / 100;
|
let sheets;
|
||||||
if (!(eth > 0)) return null;
|
let eth;
|
||||||
let sheets = Math.floor(eth / ct + 1e-12);
|
if (sheetsOverride != null && Number(sheetsOverride) > 0) {
|
||||||
|
sheets = Math.floor(Number(sheetsOverride) + 1e-12);
|
||||||
if (!(sheets > 0)) return null;
|
if (!(sheets > 0)) return null;
|
||||||
eth = Math.round(sheets * ct * 100) / 100;
|
eth = Math.round(sheets * ct * 100) / 100;
|
||||||
|
} else {
|
||||||
|
if (!(budget > 0) || !(a > 0)) return null;
|
||||||
|
eth = Math.floor((usable / a) * 100 + 1e-12) / 100;
|
||||||
|
if (!(eth > 0)) return null;
|
||||||
|
sheets = Math.floor(eth / ct + 1e-12);
|
||||||
|
if (!(sheets > 0)) return null;
|
||||||
|
eth = Math.round(sheets * ct * 100) / 100;
|
||||||
|
}
|
||||||
const perpEth = eth / ratio;
|
const perpEth = eth / ratio;
|
||||||
const contracts = perpEth / cs;
|
const contracts = perpEth / cs;
|
||||||
return {
|
return {
|
||||||
usable: usable,
|
usable: usable,
|
||||||
eth_qty: eth,
|
eth_qty: eth,
|
||||||
|
perp_qty: perpEth,
|
||||||
sheets: sheets,
|
sheets: sheets,
|
||||||
contracts: contracts,
|
contracts: contracts,
|
||||||
premium_est: a * sheets * ct,
|
premium_est: a > 0 ? a * sheets * ct : 0,
|
||||||
ratio: ratio,
|
ratio: ratio,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function currentOpSizing() {
|
||||||
|
if (!state.selected) return null;
|
||||||
|
const sheets = numInput("hp-sheets", 0);
|
||||||
|
return computeOpSizing(
|
||||||
|
state.selected.ask,
|
||||||
|
state.selected.ct_mult || 0.01,
|
||||||
|
sheets > 0 ? sheets : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatOpSizingHtml(sized, amtPrec) {
|
||||||
|
if (!sized) return "";
|
||||||
|
const coin = (state.underlying || "ETH").toUpperCase();
|
||||||
|
const prec = amtPrec != null ? amtPrec : coin === "BTC" ? 4 : 2;
|
||||||
|
return (
|
||||||
|
"期权 <strong>" +
|
||||||
|
fmt(sized.eth_qty, 2) +
|
||||||
|
"</strong> " +
|
||||||
|
coin +
|
||||||
|
" / " +
|
||||||
|
sized.sheets +
|
||||||
|
" 张 → 永续 <strong>" +
|
||||||
|
fmt(sized.perp_qty, 4) +
|
||||||
|
"</strong> " +
|
||||||
|
coin +
|
||||||
|
" (" +
|
||||||
|
fmt(sized.contracts, prec) +
|
||||||
|
" 张) · 比例 " +
|
||||||
|
fmt(sized.ratio, 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function defaultPerpLeverage(uly) {
|
function defaultPerpLeverage(uly) {
|
||||||
const u = (uly || "ETH").toUpperCase();
|
const u = (uly || "ETH").toUpperCase();
|
||||||
const btc = Number(root.getAttribute("data-btc-leverage") || 10);
|
const btc = Number(root.getAttribute("data-btc-leverage") || 10);
|
||||||
@@ -1041,22 +1106,11 @@
|
|||||||
const sz = $("hp-sizing-line");
|
const sz = $("hp-sizing-line");
|
||||||
if (sz) {
|
if (sz) {
|
||||||
if (isOptionPrimary()) {
|
if (isOptionPrimary()) {
|
||||||
const sized =
|
const sized = currentOpSizing();
|
||||||
state.selected &&
|
|
||||||
computeOpSizing(state.selected.ask, state.selected.ct_mult || 0.01);
|
|
||||||
if (sized) {
|
if (sized) {
|
||||||
sz.innerHTML =
|
sz.innerHTML = formatOpSizingHtml(sized, amtPrec);
|
||||||
"执行预算 <strong>" +
|
|
||||||
fmt(sized.usable, 2) +
|
|
||||||
"</strong> · 期权 ETH <strong>" +
|
|
||||||
fmt(sized.eth_qty, 2) +
|
|
||||||
"</strong> / " +
|
|
||||||
sized.sheets +
|
|
||||||
" 张 · 永续 <strong>" +
|
|
||||||
fmt(sized.contracts, amtPrec) +
|
|
||||||
"</strong> 张";
|
|
||||||
} else {
|
} else {
|
||||||
sz.textContent = "填写权利金并选用期权后显示定仓(权利金×0.95,ETH两位小数)";
|
sz.textContent = "填写权利金或张数并选择期权后显示定仓(默认比例2:期权÷2=永续)";
|
||||||
}
|
}
|
||||||
} else if (d.full_margin_sizing) {
|
} else if (d.full_margin_sizing) {
|
||||||
const s = d.full_margin_sizing;
|
const s = d.full_margin_sizing;
|
||||||
@@ -1301,7 +1355,7 @@
|
|||||||
(prevInst && c.inst_id === prevInst ? " active" : "") +
|
(prevInst && c.inst_id === prevInst ? " active" : "") +
|
||||||
'" data-inst="' +
|
'" data-inst="' +
|
||||||
c.inst_id +
|
c.inst_id +
|
||||||
'">选用</button></td>';
|
'">选择</button></td>';
|
||||||
tbody.appendChild(tr);
|
tbody.appendChild(tr);
|
||||||
});
|
});
|
||||||
tbody.querySelectorAll(".hp-pick").forEach(function (btn) {
|
tbody.querySelectorAll(".hp-pick").forEach(function (btn) {
|
||||||
@@ -1652,8 +1706,8 @@
|
|||||||
} else {
|
} else {
|
||||||
if (!state.selected) throw new Error("请选用期权腿");
|
if (!state.selected) throw new Error("请选用期权腿");
|
||||||
if (isOptionPrimary()) {
|
if (isOptionPrimary()) {
|
||||||
const sized = computeOpSizing(state.selected.ask, state.selected.ct_mult || 0.01);
|
const sized = currentOpSizing();
|
||||||
if (!sized) throw new Error("请填写权利金并确认卖一有效");
|
if (!sized) throw new Error("请填写权利金或张数并确认卖一有效");
|
||||||
const optPts = numInput("hp-opt-target-pts", NaN);
|
const optPts = numInput("hp-opt-target-pts", NaN);
|
||||||
const perpPts = numInput("hp-perp-target-pts", NaN);
|
const perpPts = numInput("hp-perp-target-pts", NaN);
|
||||||
if (!(optPts > 0) || !(perpPts > 0)) throw new Error("请填写期权/永续目标位点数(须大于0)");
|
if (!(optPts > 0) || !(perpPts > 0)) throw new Error("请填写期权/永续目标位点数(须大于0)");
|
||||||
@@ -1896,10 +1950,9 @@
|
|||||||
if ($("hp-opt-perp-ratio")) {
|
if ($("hp-opt-perp-ratio")) {
|
||||||
$("hp-opt-perp-ratio").addEventListener("input", function () {
|
$("hp-opt-perp-ratio").addEventListener("input", function () {
|
||||||
state.opRatioTouched = true;
|
state.opRatioTouched = true;
|
||||||
if (state.selected) {
|
const sz = $("hp-sizing-line");
|
||||||
const sized = computeOpSizing(state.selected.ask, state.selected.ct_mult || 0.01);
|
const sized = currentOpSizing();
|
||||||
if (sized && $("hp-sheets")) $("hp-sheets").value = String(sized.sheets);
|
if (sz && sized) sz.innerHTML = formatOpSizingHtml(sized);
|
||||||
}
|
|
||||||
void loadMarket();
|
void loadMarket();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -2027,7 +2080,17 @@
|
|||||||
}
|
}
|
||||||
if ($("hp-exp-select")) $("hp-exp-select").addEventListener("change", renderListStrikes);
|
if ($("hp-exp-select")) $("hp-exp-select").addEventListener("change", renderListStrikes);
|
||||||
if ($("hp-oo-exp-select")) $("hp-oo-exp-select").addEventListener("change", renderTStrikes);
|
if ($("hp-oo-exp-select")) $("hp-oo-exp-select").addEventListener("change", renderTStrikes);
|
||||||
if ($("hp-sheets")) $("hp-sheets").addEventListener("input", updatePremiumLine);
|
if ($("hp-sheets")) {
|
||||||
|
$("hp-sheets").addEventListener("input", function () {
|
||||||
|
updatePremiumLine();
|
||||||
|
if (isOptionPrimary() && state.selected) {
|
||||||
|
const sz = $("hp-sizing-line");
|
||||||
|
const sized = currentOpSizing();
|
||||||
|
if (sz && sized) sz.innerHTML = formatOpSizingHtml(sized);
|
||||||
|
void loadMarket();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
["hp-oo-sheets-a", "hp-oo-sheets-b"].forEach(function (id) {
|
["hp-oo-sheets-a", "hp-oo-sheets-b"].forEach(function (id) {
|
||||||
const el = $(id);
|
const el = $(id);
|
||||||
if (el) el.addEventListener("input", updateOoPremiumLine);
|
if (el) el.addEventListener("input", updateOoPremiumLine);
|
||||||
@@ -2631,7 +2694,7 @@
|
|||||||
index_px: indexPx() || Number(state.market.mark || 0),
|
index_px: indexPx() || Number(state.market.mark || 0),
|
||||||
entry: indexPx() || Number(state.market.mark || 0),
|
entry: indexPx() || Number(state.market.mark || 0),
|
||||||
premium_budget: prem,
|
premium_budget: prem,
|
||||||
option_perp_ratio: numInput("hp-opt-perp-ratio", 4),
|
option_perp_ratio: numInput("hp-opt-perp-ratio", 2),
|
||||||
option_target_points: optPts,
|
option_target_points: optPts,
|
||||||
perp_target_points: perpPts,
|
perp_target_points: perpPts,
|
||||||
strike_interval: numInput("hp-strike-interval", 15),
|
strike_interval: numInput("hp-strike-interval", 15),
|
||||||
@@ -2680,8 +2743,8 @@
|
|||||||
} else {
|
} else {
|
||||||
if (!state.selected) throw new Error("请选用期权腿");
|
if (!state.selected) throw new Error("请选用期权腿");
|
||||||
if (isOptionPrimary()) {
|
if (isOptionPrimary()) {
|
||||||
const sized = computeOpSizing(state.selected.ask, state.selected.ct_mult || 0.01);
|
const sized = currentOpSizing();
|
||||||
if (!sized) throw new Error("请填写权利金并确认卖一有效");
|
if (!sized) throw new Error("请填写权利金或张数并确认卖一有效");
|
||||||
const optPts = numInput("hp-opt-target-pts", NaN);
|
const optPts = numInput("hp-opt-target-pts", NaN);
|
||||||
const perpPts = numInput("hp-perp-target-pts", NaN);
|
const perpPts = numInput("hp-perp-target-pts", NaN);
|
||||||
if (!(optPts > 0) || !(perpPts > 0)) throw new Error("请填写期权/永续目标位点数(须大于0)");
|
if (!(optPts > 0) || !(perpPts > 0)) throw new Error("请填写期权/永续目标位点数(须大于0)");
|
||||||
|
|||||||
@@ -3911,6 +3911,41 @@ html[data-theme="light"] .opt-be-dist-down {
|
|||||||
.hedge-plan-page-wrap #hp-po-layout > .card {
|
.hedge-plan-page-wrap #hp-po-layout > .card {
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-left-stack,
|
||||||
|
.hedge-plan-page-wrap .hp-po-right-stack {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-left-stack > .hp-opt-card,
|
||||||
|
.hedge-plan-page-wrap .hp-po-select-card {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-left-stack > .hp-opt-card .hp-strike-table-wrap--6,
|
||||||
|
.hedge-plan-page-wrap .hp-po-select-card .hp-strike-table-wrap--6 {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 220px;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-pair-hint {
|
||||||
|
margin-left: 8px;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-chain-hint {
|
||||||
|
margin: 4px 0 8px;
|
||||||
|
font-size: 0.78rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-order-card .hp-po-perp-quote-card {
|
||||||
|
height: auto;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
.hedge-plan-page-wrap .hp-po-right-stack > .hp-po-perp-quote-card {
|
.hedge-plan-page-wrap .hp-po-right-stack > .hp-po-perp-quote-card {
|
||||||
height: auto;
|
height: auto;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ DEFAULT_PERP_LEVERAGE = 100
|
|||||||
DEFAULT_OPT_LEVERAGE_ITM_ATM = 100.0
|
DEFAULT_OPT_LEVERAGE_ITM_ATM = 100.0
|
||||||
DEFAULT_OPT_LEVERAGE_OTM = 200.0
|
DEFAULT_OPT_LEVERAGE_OTM = 200.0
|
||||||
DEFAULT_RATIO_ITM_ATM = 2.0
|
DEFAULT_RATIO_ITM_ATM = 2.0
|
||||||
DEFAULT_RATIO_OTM = 4.0
|
DEFAULT_RATIO_OTM = 2.0
|
||||||
OTM_LEV_FLOOR = 180.0
|
OTM_LEV_FLOOR = 180.0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,124 +45,22 @@
|
|||||||
|
|
||||||
<div id="hp-tab-perp_options" class="hp-tab-panel" role="tabpanel">
|
<div id="hp-tab-perp_options" class="hp-tab-panel" role="tabpanel">
|
||||||
<div class="options-dual-grid" id="hp-po-layout">
|
<div class="options-dual-grid" id="hp-po-layout">
|
||||||
<div class="card hp-po-perp-card">
|
<!-- 左:期权选择 -->
|
||||||
<h2>
|
<div class="card hp-po-left-card hp-po-select-card">
|
||||||
<span id="hp-po-mode-badge" class="hp-po-mode-badge">以期权为主</span>
|
<div class="hp-po-left-stack">
|
||||||
<span id="hp-po-card-title">执行参数</span>
|
<div class="hp-po-inner-card hp-opt-card">
|
||||||
· <span id="hp-perp-uly-label">ETH</span>
|
<h2>期权选择 · <span id="hp-opt-type-label">Call</span> <span class="muted hp-acct-tag" id="hp-opt-acct-tag">币本位</span></h2>
|
||||||
<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>(交易账户 USDT 买币开期权)。</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>:填参后点「策略启动」进入<strong>盯盘</strong>(非现场开仓);杠杆/间隔达标后自动先开期权再市价永续。右侧列表仅展示达标候选。</p>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
<div class="form-row hp-uly-row">
|
<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 active" data-uly="ETH">ETH</button>
|
||||||
<button type="button" class="btn-secondary hp-uly-btn" data-uly="BTC">BTC</button>
|
<button type="button" class="btn-secondary hp-uly-btn" data-uly="BTC">BTC</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="hp-po-top">
|
<div class="hp-po-top">
|
||||||
<div class="hp-oo-seg hp-po-dir-seg" role="group" aria-label="方向">
|
<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 is-selected" data-dir="long" title="买 Call → 永续空"><span class="hp-oo-check" aria-hidden="true">✓</span>Call</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>
|
<button type="button" class="btn-secondary hp-po-dir" data-dir="short" title="买 Put → 永续多"><span class="hp-oo-check" aria-hidden="true">✓</span>Put</button>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="muted hp-po-pair-hint" id="hp-po-pair-hint">买 Call + 永续空</span>
|
||||||
</div>
|
</div>
|
||||||
<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>
|
|
||||||
<input type="number" step="any" id="hp-entry" 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>合约张</em></span>
|
|
||||||
<input type="number" step="any" id="hp-contracts" placeholder="数量" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
|
||||||
</label>
|
|
||||||
<label class="hp-po-field hp-po-field--tp">
|
|
||||||
<span class="hp-po-field-lab">止盈 <em>USDT</em></span>
|
|
||||||
<input type="number" step="any" id="hp-tp" placeholder="目标价" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
|
||||||
</label>
|
|
||||||
<label class="hp-po-field hp-po-field--sl">
|
|
||||||
<span class="hp-po-field-lab">止损 <em>USDT</em></span>
|
|
||||||
<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 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 hp-po-fields--capital">
|
|
||||||
<label class="hp-po-field">
|
|
||||||
<span class="hp-po-field-lab">权利金 <em>币</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">永续杠杆 <em>开仓</em></span>
|
|
||||||
<input type="number" step="1" id="hp-perp-leverage" value="{{ hedge_plan_eth_leverage | default(5) }}" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" title="默认取 env 永期·永续杠杆;可按标的切换" />
|
|
||||||
</label>
|
|
||||||
<label class="hp-po-field">
|
|
||||||
<span class="hp-po-field-lab">期权杠杆 <em>启动校验</em></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 hp-po-fields--select">
|
|
||||||
<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 hp-po-field--type">
|
|
||||||
<span class="hp-po-field-lab">类型</span>
|
|
||||||
<select id="hp-money-select" aria-label="虚实值类型">
|
|
||||||
<option value="otm" selected>虚值</option>
|
|
||||||
<option value="itm">实值/平值</option>
|
|
||||||
<option value="atm">仅平值</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
<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-po-right-card">
|
|
||||||
<div class="hp-po-right-stack">
|
|
||||||
<div class="hp-po-inner-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="hp-po-inner-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">
|
<div class="form-row hp-opt-toolbar hp-po-opt-toolbar">
|
||||||
<select id="hp-exp-select"><option value="">选择到期日</option></select>
|
<select id="hp-exp-select"><option value="">选择到期日</option></select>
|
||||||
<span class="hp-po-ins-money" id="hp-po-ins-money" hidden>
|
<span class="hp-po-ins-money" id="hp-po-ins-money" hidden>
|
||||||
@@ -173,6 +71,7 @@
|
|||||||
<button type="button" class="btn-secondary" id="hp-load-chain">刷新链</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>
|
<span id="hp-index-line" class="hp-po-index" aria-live="polite">指数 —</span>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="muted hp-po-chain-hint">点「选择」填入右侧下单;比例默认 2(期权名义:永续名义),如期权 1 BTC → 永续约 0.5 BTC。</p>
|
||||||
<div class="options-strike-table-wrap hp-strike-table-wrap--6">
|
<div class="options-strike-table-wrap hp-strike-table-wrap--6">
|
||||||
<table class="options-strike-table" id="hp-strike-table">
|
<table class="options-strike-table" id="hp-strike-table">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -198,6 +97,110 @@
|
|||||||
<div id="hp-opt-bal-line" class="muted hp-po-meta hp-opt-bal-line"></div>
|
<div id="hp-opt-bal-line" class="muted hp-po-meta hp-opt-bal-line"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 右:下单参数 -->
|
||||||
|
<div class="card hp-po-right-card hp-po-order-card">
|
||||||
|
<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>:买 Call → 永续空;买 Put → 永续多。</p>
|
||||||
|
<p><strong>比例</strong>:期权:永续默认 <strong>2</strong>(期权名义 ÷ 比例 = 永续名义)。例:期权 1 BTC → 永续 0.5 BTC。</p>
|
||||||
|
<p><strong>账户</strong>:永续腿合约账户(USDT);期权腿币本位(交易账户 USDT 买币)。</p>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
<div class="hp-po-inner-card hp-po-perp-quote-card">
|
||||||
|
<h3 class="hp-po-section-title">永续行情</h3>
|
||||||
|
<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="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>
|
||||||
|
<input type="number" step="any" id="hp-entry" 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>合约张</em></span>
|
||||||
|
<input type="number" step="any" id="hp-contracts" placeholder="数量" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||||
|
</label>
|
||||||
|
<label class="hp-po-field hp-po-field--tp">
|
||||||
|
<span class="hp-po-field-lab">止盈 <em>USDT</em></span>
|
||||||
|
<input type="number" step="any" id="hp-tp" placeholder="目标价" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" />
|
||||||
|
</label>
|
||||||
|
<label class="hp-po-field hp-po-field--sl">
|
||||||
|
<span class="hp-po-field-lab">止损 <em>USDT</em></span>
|
||||||
|
<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 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 hp-po-fields--capital">
|
||||||
|
<label class="hp-po-field">
|
||||||
|
<span class="hp-po-field-lab">权利金预算 <em>币</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">永续杠杆 <em>开仓</em></span>
|
||||||
|
<input type="number" step="1" id="hp-perp-leverage" value="{{ hedge_plan_eth_leverage | default(5) }}" autocomplete="off" inputmode="numeric" data-lpignore="true" data-1p-ignore="true" data-form-type="other" title="默认取 env 永期·永续杠杆" />
|
||||||
|
</label>
|
||||||
|
<label class="hp-po-field">
|
||||||
|
<span class="hp-po-field-lab">期权杠杆 <em>校验</em></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">比例 <em>期权:永续</em></span>
|
||||||
|
<input type="number" step="any" min="0.1" id="hp-opt-perp-ratio" value="2" autocomplete="off" inputmode="decimal" data-lpignore="true" data-1p-ignore="true" data-form-type="other" title="默认2:期权名义÷比例=永续名义" />
|
||||||
|
</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 hp-po-fields--select">
|
||||||
|
<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 hp-po-field--type">
|
||||||
|
<span class="hp-po-field-lab">虚实值</span>
|
||||||
|
<select id="hp-money-select" aria-label="虚实值类型">
|
||||||
|
<option value="otm" selected>虚值</option>
|
||||||
|
<option value="itm">实值/平值</option>
|
||||||
|
<option value="atm">仅平值</option>
|
||||||
|
</select>
|
||||||
|
</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 class="form-row hp-action-row hp-po-action-row">
|
<div class="form-row hp-action-row hp-po-action-row">
|
||||||
<span id="hp-po-strategy-status" class="hp-po-strategy-status" aria-live="polite"></span>
|
<span id="hp-po-strategy-status" class="hp-po-strategy-status" aria-live="polite"></span>
|
||||||
<button type="button" class="primary" id="hp-preview-btn" title="以期权为主=盯盘启动">策略启动</button>
|
<button type="button" class="primary" id="hp-preview-btn" title="以期权为主=盯盘启动">策略启动</button>
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ class TestOptionPrimary(unittest.TestCase):
|
|||||||
"premium_budget": 100,
|
"premium_budget": 100,
|
||||||
"option_target_points": 50,
|
"option_target_points": 50,
|
||||||
"perp_target_points": 30,
|
"perp_target_points": 30,
|
||||||
"option_perp_ratio": 4,
|
"option_perp_ratio": 2,
|
||||||
"option_leverage": 200,
|
"option_leverage": 200,
|
||||||
"moneyness": "otm",
|
"moneyness": "otm",
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user