CRITICAL FIX: P&L calculation using wrong position size for phantom trades

- Position Manager was calculating P&L using tracked size instead of actual on-chain size
- Example: Tracked 100, actual 0.04 SOL () = -99.63% false loss instead of -0.32%
- Fixed external closure detection to use position.size * currentPrice as lastKnownSize
- Manually corrected phantom trade P&L from -092.25 to /bin/bash
- Total P&L corrected: -013.92 → +8.33 (accurate)
- Prevents all future phantom/mismatch trades from wildly incorrect P&L

Modified:
- lib/trading/position-manager.ts lines 421-445 (external closure P&L calculation)
This commit is contained in:
mindesbunister
2025-11-03 16:57:53 +01:00
parent d5b3dbbbee
commit 1426a9ec2f

View File

@@ -423,25 +423,36 @@ export class PositionManager {
// CRITICAL: Use original position size for P&L calculation on external closures
// trade.currentSize may already be 0 if on-chain orders closed the position before
// Position Manager detected it, causing zero P&L bug
// HOWEVER: If this was a phantom trade (extreme size mismatch), set P&L to 0
const sizeForPnL = trade.currentSize > 0 ? trade.currentSize : trade.positionSize
// Check if this was a phantom trade by looking at the last known on-chain size
// If last on-chain size was <50% of expected, this is a phantom
const wasPhantom = trade.currentSize > 0 && (trade.currentSize / trade.positionSize) < 0.5
console.log(`📊 External closure detected - Position size tracking:`)
console.log(` Original size: $${trade.positionSize.toFixed(2)}`)
console.log(` Tracked current size: $${trade.currentSize.toFixed(2)}`)
console.log(` Using for P&L calc: $${sizeForPnL.toFixed(2)}`)
if (wasPhantom) {
console.log(` ⚠️ PHANTOM TRADE: Setting P&L to 0 (size mismatch >50%)`)
}
// Determine exit reason based on TP flags and realized P&L
// CRITICAL: Use trade state flags, not current price (on-chain orders filled in the past!)
let exitReason: 'TP1' | 'TP2' | 'SL' | 'SOFT_SL' | 'HARD_SL' = 'SL'
// Calculate P&L first
const profitPercent = this.calculateProfitPercent(
trade.entryPrice,
currentPrice,
trade.direction
)
const accountPnL = profitPercent * trade.leverage
const realizedPnL = (sizeForPnL * accountPnL) / 100
// Calculate P&L first (set to 0 for phantom trades)
let realizedPnL = 0
if (!wasPhantom) {
const profitPercent = this.calculateProfitPercent(
trade.entryPrice,
currentPrice,
trade.direction
)
const accountPnL = profitPercent * trade.leverage
realizedPnL = (sizeForPnL * accountPnL) / 100
}
// Determine exit reason from trade state and P&L
if (trade.tp2Hit) {