Fix max option sheets: shared trading USDT = buy premium + perp margin.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -506,46 +506,50 @@
|
|||||||
return Number.isFinite(eth) && eth > 0 ? eth : 5;
|
return Number.isFinite(eth) && eth > 0 ? eth : 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 按交易账户 USDT(买币+5%滑点)与合约账户永续杠杆算最大期权张数. */
|
/**
|
||||||
|
* 期权开仓最大张数:OKX 交易账户 USDT 共用.
|
||||||
|
* 每张开仓需:买币(权利金×1.05×指数) + 永续保证金(对冲名义÷杠杆);
|
||||||
|
* 选最大 N 时须保证扣完买币后剩余仍够永续保证金.
|
||||||
|
*/
|
||||||
function computeMaxSheets() {
|
function computeMaxSheets() {
|
||||||
const ask = state.selected && Number(state.selected.ask);
|
const ask = state.selected && Number(state.selected.ask);
|
||||||
const ct = Number((state.selected && state.selected.ct_mult) || 0.01);
|
const ct = Number((state.selected && state.selected.ct_mult) || 0.01);
|
||||||
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 mark = Number(
|
||||||
const mark = Number((state.market && (state.market.mark || state.market.index_px)) || indexPx() || 0);
|
(state.market && (state.market.mark || state.market.index_px)) || indexPx() || 0
|
||||||
|
);
|
||||||
const lev = defaultPerpLeverage(state.underlying);
|
const lev = defaultPerpLeverage(state.underlying);
|
||||||
const tradingUsdt = Number(state.tradingUsdt != null ? state.tradingUsdt : state.tradingUsdc);
|
const tradingUsdt = Number(
|
||||||
const perpAvail = Number((state.market && state.market.available_usdt) || 0);
|
state.tradingUsdt != null ? state.tradingUsdt : state.tradingUsdc
|
||||||
if (!(ask > 0) || !(ct > 0) || !(ratio > 0) || !(cs > 0) || !(mark > 0) || !(lev > 0)) {
|
);
|
||||||
|
if (!(ask > 0) || !(ct > 0) || !(ratio > 0) || !(mark > 0) || !(lev > 0)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 买币:权利金币×1.05×指数 ≈ 所需 USDT
|
if (!(tradingUsdt > 0)) {
|
||||||
const coinPerSheet = ask * ct;
|
return {
|
||||||
const usdtPerSheet = coinPerSheet * 1.05 * mark;
|
max_sheets: 0,
|
||||||
let maxByOpt = Infinity;
|
lev: lev,
|
||||||
if (tradingUsdt > 0 && usdtPerSheet > 0) {
|
trading_usdt: tradingUsdt,
|
||||||
maxByOpt = Math.floor(tradingUsdt / usdtPerSheet + 1e-12);
|
buy_usdt_per_sheet: 0,
|
||||||
|
margin_per_sheet: 0,
|
||||||
|
total_per_sheet: 0,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// 永续:名义 = 保证金×杠杆; 永续币 = 期权币/比例; 合约张 = 永续币/cs
|
// 买币 USDT/张 = 权利金币 × 1.05 × 指数
|
||||||
// 期权张 n → 永续名义 = (n*ct/ratio)*mark ≤ avail*lev
|
const buyUsdtPerSheet = ask * ct * 1.05 * mark;
|
||||||
let maxByPerp = Infinity;
|
// 永续名义/张 = (期权币/比例)×指数; 保证金 = 名义÷杠杆
|
||||||
if (perpAvail > 0) {
|
const perpNotionalPerSheet = (ct / ratio) * mark;
|
||||||
const maxPerpNotional = perpAvail * lev;
|
const marginPerSheet = perpNotionalPerSheet / lev;
|
||||||
const notionalPerSheet = (ct / ratio) * mark;
|
const totalPerSheet = buyUsdtPerSheet + marginPerSheet;
|
||||||
if (notionalPerSheet > 0) {
|
if (!(totalPerSheet > 0)) return null;
|
||||||
maxByPerp = Math.floor(maxPerpNotional / notionalPerSheet + 1e-12);
|
const maxSheets = Math.max(0, Math.floor(tradingUsdt / totalPerSheet + 1e-12));
|
||||||
}
|
|
||||||
}
|
|
||||||
const maxSheets = Math.max(0, Math.min(maxByOpt, maxByPerp));
|
|
||||||
if (!(maxSheets > 0) && !(tradingUsdt > 0) && !(perpAvail > 0)) return null;
|
|
||||||
return {
|
return {
|
||||||
max_sheets: maxSheets,
|
max_sheets: maxSheets,
|
||||||
max_by_opt: Number.isFinite(maxByOpt) ? maxByOpt : null,
|
|
||||||
max_by_perp: Number.isFinite(maxByPerp) ? maxByPerp : null,
|
|
||||||
lev: lev,
|
lev: lev,
|
||||||
trading_usdt: tradingUsdt,
|
trading_usdt: tradingUsdt,
|
||||||
perp_avail: perpAvail,
|
buy_usdt_per_sheet: buyUsdtPerSheet,
|
||||||
usdt_per_sheet: usdtPerSheet,
|
margin_per_sheet: marginPerSheet,
|
||||||
|
total_per_sheet: totalPerSheet,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,23 +560,37 @@
|
|||||||
const sized = currentOpSizing();
|
const sized = currentOpSizing();
|
||||||
const coin = (state.underlying || "ETH").toUpperCase();
|
const coin = (state.underlying || "ETH").toUpperCase();
|
||||||
const lev = defaultPerpLeverage(state.underlying);
|
const lev = defaultPerpLeverage(state.underlying);
|
||||||
|
const mark = Number(
|
||||||
|
(state.market && (state.market.mark || state.market.index_px)) || indexPx() || 0
|
||||||
|
);
|
||||||
if (maxEl) {
|
if (maxEl) {
|
||||||
if (maxInfo) {
|
if (maxInfo) {
|
||||||
maxEl.innerHTML =
|
maxEl.innerHTML =
|
||||||
"最大约 <strong>" +
|
"期权开仓最大 <strong>" +
|
||||||
maxInfo.max_sheets +
|
maxInfo.max_sheets +
|
||||||
"</strong> 张 · 永续杠杆 " +
|
"</strong> 张 · 交易 USDT " +
|
||||||
lev +
|
|
||||||
"x(env) · 交易 USDT " +
|
|
||||||
fmt(maxInfo.trading_usdt, 2) +
|
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 {
|
} else {
|
||||||
maxEl.textContent = "选择期权并刷新行情后显示最大开仓张数(交易账户买币+永续杠杆)";
|
maxEl.textContent =
|
||||||
|
"选择期权并刷新后显示:期权开仓最大张数(扣买币后剩余须够永续保证金)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (perpEl) {
|
if (perpEl) {
|
||||||
if (sized) {
|
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 =
|
perpEl.innerHTML =
|
||||||
"永续自动开 <strong>" +
|
"永续自动开 <strong>" +
|
||||||
fmt(sized.perp_qty, 4) +
|
fmt(sized.perp_qty, 4) +
|
||||||
@@ -584,7 +602,14 @@
|
|||||||
fmt(sized.premium_est * 1.05, 4) +
|
fmt(sized.premium_est * 1.05, 4) +
|
||||||
" " +
|
" " +
|
||||||
coin +
|
coin +
|
||||||
"(含5%滑点)";
|
"(≈" +
|
||||||
|
fmt(buyUsdt, 2) +
|
||||||
|
" U含5%) · 扣后剩 " +
|
||||||
|
fmt(remain, 2) +
|
||||||
|
" U · 永续保证金约 " +
|
||||||
|
fmt(marginUsdt, 2) +
|
||||||
|
" U" +
|
||||||
|
(marginOk ? "" : ' <span class="is-err">不足</span>');
|
||||||
} else {
|
} else {
|
||||||
perpEl.textContent = "永续开仓 — (填张数并选择期权后按比例自动算)";
|
perpEl.textContent = "永续开仓 — (填张数并选择期权后按比例自动算)";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user