diff --git a/lib/common/static/options_panel.js b/lib/common/static/options_panel.js index 1dfaeac..c2f7a69 100644 --- a/lib/common/static/options_panel.js +++ b/lib/common/static/options_panel.js @@ -856,6 +856,19 @@ return Math.round((value - prem) * 100) / 100; } + /** 盈亏比 = 盈利金额 / 本合约权利金(目标位仅作到期实值参考). */ + function estimateProfitRr(profit, totalPremium) { + const pnl = Number(profit); + const prem = Number(totalPremium); + if (!Number.isFinite(pnl) || !Number.isFinite(prem) || prem <= 0) return null; + return Math.round((pnl / prem) * 100) / 100; + } + + function fmtProfitRr(v) { + if (v === null || v === undefined || Number.isNaN(Number(v))) return "—"; + return Number(v).toFixed(2); + } + function calcContractLeverage(indexPx, ethAmount, totalPremium) { if (indexPx == null || ethAmount == null || totalPremium == null) return null; const idx = Number(indexPx); @@ -897,7 +910,7 @@ const levEl = document.getElementById("opt-order-leverage"); const valueEl = document.getElementById("opt-est-value"); const profitEl = document.getElementById("opt-est-profit"); - const targetLevEl = document.getElementById("opt-est-leverage"); + const rrEl = document.getElementById("opt-est-rr") || document.getElementById("opt-est-leverage"); const targetEl = document.getElementById("opt-target-idx"); const q = state.orderQuote; if (!q || !q.ok || !q.can_open) { @@ -907,7 +920,10 @@ profitEl.textContent = "—"; profitEl.className = "v"; } - if (targetLevEl) targetLevEl.textContent = "—"; + if (rrEl) { + rrEl.textContent = "—"; + rrEl.className = "v"; + } return; } const sz = q.sizing || {}; @@ -922,10 +938,14 @@ valueEl.textContent = "—"; profitEl.textContent = "—"; profitEl.className = "v"; - if (targetLevEl) targetLevEl.textContent = "—"; + if (rrEl) { + rrEl.textContent = "—"; + rrEl.className = "v"; + } } else { const value = estimateExpiryValue(q.opt_type, q.strike, Number(targetRaw), ethAmount); const profit = estimateExpiryProfit(q.opt_type, q.strike, Number(targetRaw), ethAmount, premium); + const rr = estimateProfitRr(profit, premium); if (value == null || Number.isNaN(value)) { valueEl.textContent = "—"; } else { @@ -938,8 +958,15 @@ profitEl.textContent = fmtUsdcSigned(profit); profitEl.className = "v " + pnlCls(profit); } - const targetLev = calcContractLeverage(Number(targetRaw), ethAmount, premium); - if (targetLevEl) targetLevEl.textContent = fmtLeverage(targetLev); + if (rrEl) { + if (rr == null || Number.isNaN(rr)) { + rrEl.textContent = "—"; + rrEl.className = "v"; + } else { + rrEl.textContent = fmtProfitRr(rr); + rrEl.className = "v " + pnlCls(rr); + } + } } } } @@ -1431,12 +1458,15 @@ function formatTargetEstimateHtml(optType, strike, targetIdx, ethAmount, premiumPaid) { const value = estimateExpiryValue(optType, strike, targetIdx, ethAmount); const profit = estimateExpiryProfit(optType, strike, targetIdx, ethAmount, premiumPaid); - if (value == null && profit == null) return ""; + const rr = estimateProfitRr(profit, premiumPaid); + if (value == null && profit == null && rr == null) return ""; let html = ''; html += '价值' + (value == null ? "—" : fmtUsdc(value) + " USDC") + ""; html += '预估盈利' + (profit == null ? "—" : fmtUsdcSigned(profit)) + ""; + html += '盈亏比' + + (rr == null ? "—" : fmtProfitRr(rr)) + ""; html += ""; return html; } @@ -1500,7 +1530,7 @@ : "") + estHtml + '' + - (armed ? "监控中 · 到位按买一限价平" : "输入后设定 · 到位按买一限价平 · 到期即止损") + + (armed ? "监控中 · 目标位参考 · 到位按买一限价平" : "目标位参考(到期实值估盈亏比) · 到位按买一限价平 · 到期即止损") + "" + "" ); diff --git a/lib/options/templates/options_panel.html b/lib/options/templates/options_panel.html index c9546ca..161c831 100644 --- a/lib/options/templates/options_panel.html +++ b/lib/options/templates/options_panel.html @@ -107,17 +107,17 @@
- +