From 4b841bc5f4c9e9abe031e7c2dd5c04021b76f3ae Mon Sep 17 00:00:00 2001 From: root Date: Sun, 1 Mar 2026 09:48:46 +0000 Subject: [PATCH] fix: floating PnL now accounts for half-position after TP1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: unrealR = full position × price move (wrong after TP1) After: unrealR = 0.5×TP1_locked + 0.5×current_float (correct) This fixes the display showing >1R floating profit that never materializes in final PnL because only half position remains. --- frontend/app/paper/page.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/app/paper/page.tsx b/frontend/app/paper/page.tsx index cb01b0b..c7b6a14 100644 --- a/frontend/app/paper/page.tsx +++ b/frontend/app/paper/page.tsx @@ -213,7 +213,10 @@ function ActivePositions() { const entry = p.entry_price || 0; const atr = p.atr_at_entry || 1; const riskDist = 2.0 * 0.7 * atr; - const unrealR = riskDist > 0 ? (p.direction === "LONG" ? (currentPrice - entry) / riskDist : (entry - currentPrice) / riskDist) : 0; + // TP1触发后只剩半仓:0.5×TP1锁定 + 0.5×当前浮盈 + 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 unrealR = p.tp1_hit ? 0.5 * tp1R + 0.5 * fullR : fullR; const unrealUsdt = unrealR * 200; return (