Show equivalent contract leverage on options order panel.

Display notional-over-premium leverage at current index and at the user target price for quick sizing comparison.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-07 16:58:25 +08:00
parent 27921213b0
commit 25879dd007
4 changed files with 79 additions and 20 deletions
+53 -19
View File
@@ -184,33 +184,67 @@
return Math.round((intrinsic - entry) * amt * 10000) / 10000;
}
function updateEstimatedProfit() {
const el = document.getElementById("opt-est-profit");
function calcContractLeverage(indexPx, ethAmount, totalPremium) {
if (indexPx == null || ethAmount == null || totalPremium == null) return null;
const idx = Number(indexPx);
const amt = Number(ethAmount);
const prem = Number(totalPremium);
if (!Number.isFinite(idx) || !Number.isFinite(amt) || !Number.isFinite(prem) || amt <= 0 || prem <= 0) {
return null;
}
return Math.round((idx * amt) / prem * 10) / 10;
}
function fmtLeverage(v) {
if (v === null || v === undefined || Number.isNaN(Number(v))) return "—";
return "约 " + Number(v).toFixed(1) + "×";
}
function updateOrderEstimates() {
const levEl = document.getElementById("opt-order-leverage");
const profitEl = document.getElementById("opt-est-profit");
const targetLevEl = document.getElementById("opt-est-leverage");
const targetEl = document.getElementById("opt-target-idx");
if (!el || !targetEl) return;
const q = state.orderQuote;
if (!q || !q.ok) {
el.textContent = "—";
el.className = "v";
return;
}
const targetRaw = targetEl.value;
if (targetRaw === "" || targetRaw == null) {
el.textContent = "—";
el.className = "v";
if (levEl) levEl.textContent = "—";
if (profitEl) {
profitEl.textContent = "—";
profitEl.className = "v";
}
if (targetLevEl) targetLevEl.textContent = "";
return;
}
const sz = q.sizing || {};
const ethAmount = sz.eth_amount;
const profit = estimateExpiryProfit(q.opt_type, q.strike, Number(targetRaw), q.ask, ethAmount);
if (profit == null || Number.isNaN(profit)) {
el.textContent = "—";
el.className = "v";
return;
const premium = sz.total_premium;
const lev = calcContractLeverage(q.index_px, ethAmount, premium);
if (levEl) levEl.textContent = fmtLeverage(lev);
if (profitEl && targetEl) {
const targetRaw = targetEl.value;
if (targetRaw === "" || targetRaw == null) {
profitEl.textContent = "—";
profitEl.className = "v";
if (targetLevEl) targetLevEl.textContent = "—";
} else {
const profit = estimateExpiryProfit(q.opt_type, q.strike, Number(targetRaw), q.ask, ethAmount);
if (profit == null || Number.isNaN(profit)) {
profitEl.textContent = "—";
profitEl.className = "v";
} else {
const sign = profit > 0 ? "+" : "";
profitEl.textContent = sign + profit.toFixed(4) + " USDC";
profitEl.className = "v " + pnlCls(profit);
}
const targetLev = calcContractLeverage(Number(targetRaw), ethAmount, premium);
if (targetLevEl) targetLevEl.textContent = fmtLeverage(targetLev);
}
}
const sign = profit > 0 ? "+" : "";
el.textContent = sign + profit.toFixed(4) + " USDC";
el.className = "v " + pnlCls(profit);
}
function updateEstimatedProfit() {
updateOrderEstimates();
}
function fmtDist(v) {