fix: frontend use DB risk_distance + add entry time with ms

- Both paper pages now read risk_distance from API (not hardcoded 2.0*0.7*ATR)
- Added entry timestamp display (精确到毫秒) in active positions
- Applies to both V5.1 and V5.2 paper pages
This commit is contained in:
root 2026-03-02 07:13:52 +00:00
parent 88290882f9
commit a7dec3fe14
2 changed files with 5 additions and 5 deletions

View File

@ -290,8 +290,7 @@ function ActivePositions({ strategy }: { strategy: StrategyFilter }) {
const frScore = factors?.funding_rate?.score ?? 0; const frScore = factors?.funding_rate?.score ?? 0;
const liqScore = factors?.liquidation?.score ?? 0; const liqScore = factors?.liquidation?.score ?? 0;
const entry = p.entry_price || 0; const entry = p.entry_price || 0;
const atr = p.atr_at_entry || 1; const riskDist = p.risk_distance || Math.abs(entry - (p.sl_price || entry)) || 1;
const riskDist = 2.0 * 0.7 * atr;
const fullR = riskDist > 0 ? (p.direction === "LONG" ? (currentPrice - entry) / riskDist : (entry - currentPrice) / riskDist) : 0; const fullR = riskDist > 0 ? (p.direction === "LONG" ? (currentPrice - entry) / riskDist : (entry - currentPrice) / riskDist) : 0;
const tp1R = riskDist > 0 ? (p.direction === "LONG" ? ((p.tp1_price || 0) - entry) / riskDist : (entry - (p.tp1_price || 0)) / riskDist) : 0; const tp1R = riskDist > 0 ? (p.direction === "LONG" ? ((p.tp1_price || 0) - entry) / riskDist : (entry - (p.tp1_price || 0)) / riskDist) : 0;
const unrealR = p.tp1_hit ? 0.5 * tp1R + 0.5 * fullR : fullR; const unrealR = p.tp1_hit ? 0.5 * tp1R + 0.5 * fullR : fullR;
@ -322,6 +321,7 @@ function ActivePositions({ strategy }: { strategy: StrategyFilter }) {
</div> </div>
<div className="flex gap-3 mt-1 text-[10px] font-mono text-slate-600 flex-wrap"> <div className="flex gap-3 mt-1 text-[10px] font-mono text-slate-600 flex-wrap">
<span>入场: ${fmtPrice(p.entry_price)}</span> <span>入场: ${fmtPrice(p.entry_price)}</span>
<span className="text-slate-400">{new Date(p.entry_ts).toLocaleString("zh-CN", {hour12:false, month:"2-digit", day:"2-digit", hour:"2-digit", minute:"2-digit", second:"2-digit", fractionalSecondDigits:3} as any)}</span>
<span className="text-blue-600">现价: ${currentPrice ? fmtPrice(currentPrice) : "-"}</span> <span className="text-blue-600">现价: ${currentPrice ? fmtPrice(currentPrice) : "-"}</span>
<span className="text-emerald-600">TP1: ${fmtPrice(p.tp1_price)}{p.tp1_hit ? " ✅" : ""}</span> <span className="text-emerald-600">TP1: ${fmtPrice(p.tp1_price)}{p.tp1_hit ? " ✅" : ""}</span>
<span className="text-emerald-600">TP2: ${fmtPrice(p.tp2_price)}</span> <span className="text-emerald-600">TP2: ${fmtPrice(p.tp2_price)}</span>

View File

@ -226,8 +226,7 @@ function ActivePositions() {
const holdMin = Math.round((Date.now() - p.entry_ts) / 60000); const holdMin = Math.round((Date.now() - p.entry_ts) / 60000);
const currentPrice = wsPrices[p.symbol] || p.current_price || 0; const currentPrice = wsPrices[p.symbol] || p.current_price || 0;
const entry = p.entry_price || 0; const entry = p.entry_price || 0;
const atr = p.atr_at_entry || 1; const riskDist = p.risk_distance || Math.abs(entry - (p.sl_price || entry)) || 1;
const riskDist = 2.0 * 0.7 * atr;
// TP1触发后只剩半仓0.5×TP1锁定 + 0.5×当前浮盈 // TP1触发后只剩半仓0.5×TP1锁定 + 0.5×当前浮盈
const fullR = riskDist > 0 ? (p.direction === "LONG" ? (currentPrice - entry) / riskDist : (entry - currentPrice) / riskDist) : 0; const fullR = riskDist > 0 ? (p.direction === "LONG" ? (currentPrice - entry) / riskDist : (entry - currentPrice) / riskDist) : 0;
const tp1R = riskDist > 0 ? (p.direction === "LONG" ? ((p.tp1_price || 0) - entry) / riskDist : (entry - (p.tp1_price || 0)) / riskDist) : 0; const tp1R = riskDist > 0 ? (p.direction === "LONG" ? ((p.tp1_price || 0) - entry) / riskDist : (entry - (p.tp1_price || 0)) / riskDist) : 0;
@ -252,8 +251,9 @@ function ActivePositions() {
<span className="text-[10px] text-slate-400">{holdMin}m</span> <span className="text-[10px] text-slate-400">{holdMin}m</span>
</div> </div>
</div> </div>
<div className="flex gap-3 mt-1 text-[10px] font-mono text-slate-600"> <div className="flex gap-3 mt-1 text-[10px] font-mono text-slate-600 flex-wrap">
<span>入场: ${fmtPrice(p.entry_price)}</span> <span>入场: ${fmtPrice(p.entry_price)}</span>
<span className="text-slate-400">{new Date(p.entry_ts).toLocaleString("zh-CN", {hour12:false, year:undefined, month:"2-digit", day:"2-digit", hour:"2-digit", minute:"2-digit", second:"2-digit", fractionalSecondDigits:3} as any)}</span>
<span className="text-blue-600">现价: ${currentPrice ? fmtPrice(currentPrice) : "-"}</span> <span className="text-blue-600">现价: ${currentPrice ? fmtPrice(currentPrice) : "-"}</span>
<span className="text-emerald-600">TP1: ${fmtPrice(p.tp1_price)}{p.tp1_hit ? " ✅" : ""}</span> <span className="text-emerald-600">TP1: ${fmtPrice(p.tp1_price)}{p.tp1_hit ? " ✅" : ""}</span>
<span className="text-emerald-600">TP2: ${fmtPrice(p.tp2_price)}</span> <span className="text-emerald-600">TP2: ${fmtPrice(p.tp2_price)}</span>