diff --git a/lib/common/static/hedge_plan.js b/lib/common/static/hedge_plan.js
index 6576ba3..4c35a65 100644
--- a/lib/common/static/hedge_plan.js
+++ b/lib/common/static/hedge_plan.js
@@ -506,46 +506,50 @@
return Number.isFinite(eth) && eth > 0 ? eth : 5;
}
- /** 按交易账户 USDT(买币+5%滑点)与合约账户永续杠杆算最大期权张数. */
+ /**
+ * 期权开仓最大张数:OKX 交易账户 USDT 共用.
+ * 每张开仓需:买币(权利金×1.05×指数) + 永续保证金(对冲名义÷杠杆);
+ * 选最大 N 时须保证扣完买币后剩余仍够永续保证金.
+ */
function computeMaxSheets() {
const ask = state.selected && Number(state.selected.ask);
const ct = Number((state.selected && state.selected.ct_mult) || 0.01);
const ratio = numInput("hp-opt-perp-ratio", 2);
- const cs = Number((state.market && state.market.contract_size) || 0.01);
- const mark = Number((state.market && (state.market.mark || state.market.index_px)) || indexPx() || 0);
+ const mark = Number(
+ (state.market && (state.market.mark || state.market.index_px)) || indexPx() || 0
+ );
const lev = defaultPerpLeverage(state.underlying);
- const tradingUsdt = Number(state.tradingUsdt != null ? state.tradingUsdt : state.tradingUsdc);
- const perpAvail = Number((state.market && state.market.available_usdt) || 0);
- if (!(ask > 0) || !(ct > 0) || !(ratio > 0) || !(cs > 0) || !(mark > 0) || !(lev > 0)) {
+ const tradingUsdt = Number(
+ state.tradingUsdt != null ? state.tradingUsdt : state.tradingUsdc
+ );
+ if (!(ask > 0) || !(ct > 0) || !(ratio > 0) || !(mark > 0) || !(lev > 0)) {
return null;
}
- // 买币:权利金币×1.05×指数 ≈ 所需 USDT
- const coinPerSheet = ask * ct;
- const usdtPerSheet = coinPerSheet * 1.05 * mark;
- let maxByOpt = Infinity;
- if (tradingUsdt > 0 && usdtPerSheet > 0) {
- maxByOpt = Math.floor(tradingUsdt / usdtPerSheet + 1e-12);
+ if (!(tradingUsdt > 0)) {
+ return {
+ max_sheets: 0,
+ lev: lev,
+ trading_usdt: tradingUsdt,
+ buy_usdt_per_sheet: 0,
+ margin_per_sheet: 0,
+ total_per_sheet: 0,
+ };
}
- // 永续:名义 = 保证金×杠杆; 永续币 = 期权币/比例; 合约张 = 永续币/cs
- // 期权张 n → 永续名义 = (n*ct/ratio)*mark ≤ avail*lev
- let maxByPerp = Infinity;
- if (perpAvail > 0) {
- const maxPerpNotional = perpAvail * lev;
- const notionalPerSheet = (ct / ratio) * mark;
- if (notionalPerSheet > 0) {
- maxByPerp = Math.floor(maxPerpNotional / notionalPerSheet + 1e-12);
- }
- }
- const maxSheets = Math.max(0, Math.min(maxByOpt, maxByPerp));
- if (!(maxSheets > 0) && !(tradingUsdt > 0) && !(perpAvail > 0)) return null;
+ // 买币 USDT/张 = 权利金币 × 1.05 × 指数
+ const buyUsdtPerSheet = ask * ct * 1.05 * mark;
+ // 永续名义/张 = (期权币/比例)×指数; 保证金 = 名义÷杠杆
+ const perpNotionalPerSheet = (ct / ratio) * mark;
+ const marginPerSheet = perpNotionalPerSheet / lev;
+ const totalPerSheet = buyUsdtPerSheet + marginPerSheet;
+ if (!(totalPerSheet > 0)) return null;
+ const maxSheets = Math.max(0, Math.floor(tradingUsdt / totalPerSheet + 1e-12));
return {
max_sheets: maxSheets,
- max_by_opt: Number.isFinite(maxByOpt) ? maxByOpt : null,
- max_by_perp: Number.isFinite(maxByPerp) ? maxByPerp : null,
lev: lev,
trading_usdt: tradingUsdt,
- perp_avail: perpAvail,
- usdt_per_sheet: usdtPerSheet,
+ buy_usdt_per_sheet: buyUsdtPerSheet,
+ margin_per_sheet: marginPerSheet,
+ total_per_sheet: totalPerSheet,
};
}
@@ -556,23 +560,37 @@
const sized = currentOpSizing();
const coin = (state.underlying || "ETH").toUpperCase();
const lev = defaultPerpLeverage(state.underlying);
+ const mark = Number(
+ (state.market && (state.market.mark || state.market.index_px)) || indexPx() || 0
+ );
if (maxEl) {
if (maxInfo) {
maxEl.innerHTML =
- "最大约 " +
+ "期权开仓最大 " +
maxInfo.max_sheets +
- " 张 · 永续杠杆 " +
- lev +
- "x(env) · 交易 USDT " +
+ " 张 · 交易 USDT " +
fmt(maxInfo.trading_usdt, 2) +
- " · 合约可用 " +
- fmt(maxInfo.perp_avail, 2);
+ " · 每张约买币 " +
+ fmt(maxInfo.buy_usdt_per_sheet, 2) +
+ " + 永续保证金 " +
+ fmt(maxInfo.margin_per_sheet, 2) +
+ " (杠杆 " +
+ lev +
+ "x)";
} else {
- maxEl.textContent = "选择期权并刷新行情后显示最大开仓张数(交易账户买币+永续杠杆)";
+ maxEl.textContent =
+ "选择期权并刷新后显示:期权开仓最大张数(扣买币后剩余须够永续保证金)";
}
}
if (perpEl) {
if (sized) {
+ const buyUsdt = sized.premium_est * 1.05 * (mark > 0 ? mark : 0);
+ const marginUsdt =
+ sized.perp_qty * (mark > 0 ? mark : 0) / (lev > 0 ? lev : 1);
+ const remain =
+ Number(state.tradingUsdt != null ? state.tradingUsdt : state.tradingUsdc) -
+ buyUsdt;
+ const marginOk = remain + 1e-9 >= marginUsdt;
perpEl.innerHTML =
"永续自动开 " +
fmt(sized.perp_qty, 4) +
@@ -584,7 +602,14 @@
fmt(sized.premium_est * 1.05, 4) +
" " +
coin +
- "(含5%滑点)";
+ "(≈" +
+ fmt(buyUsdt, 2) +
+ " U含5%) · 扣后剩 " +
+ fmt(remain, 2) +
+ " U · 永续保证金约 " +
+ fmt(marginUsdt, 2) +
+ " U" +
+ (marginOk ? "" : ' 不足');
} else {
perpEl.textContent = "永续开仓 — (填张数并选择期权后按比例自动算)";
}