diff --git a/index.html b/index.html
index e92df3f..be2c86c 100644
--- a/index.html
+++ b/index.html
@@ -69,6 +69,7 @@
transition:border-color .15s;
}
input[type=number]:focus{border-color:var(--border-hi)}
+ input[type=number]:disabled{opacity:.5;cursor:not-allowed}
input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.side-toggle{display:flex;gap:8px}
@@ -172,8 +173,15 @@
@@ -198,15 +206,25 @@
—
-
@@ -229,8 +247,9 @@
- 说明:真正把亏损锁定在风险金额的是止损单,不是杠杆。表中「状态」校验爆仓价是否在止损之外——
- 安全表示会先触发止损、不会被强平;危险表示杠杆过高、爆仓在止损之前。
+ 说明:真正把亏损锁定在风险金额的是止损单,不是杠杆。止盈默认按盈亏比自动反算——
+ 止盈点位差 = 止损点位差 × 盈亏比 R,按方向算出止盈价;也可切「按价格」手动输入。
+ 表中「状态」校验爆仓价是否在止损之外——安全表示会先触发止损、不会被强平;危险表示杠杆过高、爆仓在止损之前。
爆仓价为逐仓简化估算(爆仓距离≈1/杠杆,忽略维持保证金与手续费),实盘以交易所显示为准。这只是数学计算,不构成投资建议。
@@ -239,7 +258,7 @@
(function(){
const $=id=>document.getElementById(id);
const levs=[3,5,10,20,25,50,75,100];
- let side='long', slMode='pct';
+ let side='long', slMode='pct', tpMode='rr';
// side toggle
$('side').addEventListener('click',e=>{
@@ -258,7 +277,17 @@
calc();
});
- ['balance','riskPct','entry','slPct','slPrice','tp'].forEach(id=>$(id).addEventListener('input',calc));
+ // take-profit mode toggle
+ $('tpMode').addEventListener('click',e=>{
+ const b=e.target.closest('button'); if(!b)return;
+ tpMode=b.dataset.mode;
+ [...$('tpMode').children].forEach(x=>x.classList.toggle('on',x===b));
+ $('tpRR').disabled = tpMode!=='rr';
+ $('tp').disabled = tpMode!=='price';
+ calc();
+ });
+
+ ['balance','riskPct','entry','slPct','slPrice','tp','tpRR'].forEach(id=>$(id).addEventListener('input',calc));
const fmtN=(n,d=2)=>isFinite(n)?n.toLocaleString('en-US',{minimumFractionDigits:d,maximumFractionDigits:d}):'—';
const fmtP=n=>isFinite(n)?n.toLocaleString('en-US',{minimumFractionDigits:5,maximumFractionDigits:5}):'—';
@@ -292,15 +321,32 @@
$('slPriceShow').textContent = fmtP(slPrice);
$('slShow').textContent = '止损 '+fmtN(slPctVal)+'%';
- // take profit / RR
- const tp=+$('tp').value;
- if(tp>0){
- const tpDist=Math.abs(tp-entry);
+ // take profit — 两种模式:按盈亏比反算 / 按价格
+ let tpPrice, rr;
+ if(tpMode==='rr'){
+ rr=+$('tpRR').value; // 目标盈亏比
+ if(rr>0){
+ // 止盈点位差 = 止损点位差 × 盈亏比,按方向反算止盈价
+ tpPrice = side==='long' ? entry + dist*rr : entry - dist*rr;
+ $('tp').value = (+tpPrice.toPrecision(8)); // 同步显示到价格框,方便核对/切换
+ }
+ }else{
+ tpPrice=+$('tp').value;
+ if(tpPrice>0) rr = Math.abs(tpPrice-entry)/dist;
+ }
+
+ if(tpPrice>0 && rr>0){
+ const tpDist=Math.abs(tpPrice-entry);
const profit=qty*tpDist;
- const rr=tpDist/dist;
+ const tpPct=tpDist/entry*100;
$('rr').textContent = '1 : '+fmtN(rr);
+ $('tpPriceShow').textContent = fmtP(tpPrice);
$('tpProfit').innerHTML = '+'+fmtN(profit)+' U';
- }else{ $('rr').textContent='—'; $('tpProfit').textContent='—'; }
+ $('tpPctShow').textContent = fmtN(tpPct)+'%';
+ }else{
+ $('rr').textContent='—'; $('tpPriceShow').textContent='—';
+ $('tpProfit').textContent='—'; $('tpPctShow').textContent='—';
+ }
// leverage ladder
const rows=levs.map(L=>{
@@ -321,7 +367,7 @@
}
function clearOut(){
- ['qty','notional','rr','slPriceShow','tpProfit'].forEach(id=>$(id).textContent='—');
+ ['qty','notional','rr','slPriceShow','tpPriceShow','tpProfit','tpPctShow'].forEach(id=>$(id).textContent='—');
$('slShow').textContent=''; $('ladder').innerHTML='';
}