Fix Position Manager bug: prevent cancelling orders when tracking old trades

Bug: Position Manager was comparing ANY position on the symbol to the trade being
tracked, without verifying entry price match. When a new position opened, it would
think the old tracked trade 'closed externally' and cancel ALL orders - including
the new position's exit orders.

Fix: Added entry price verification (0.5% tolerance). If position entry price doesn't
match the tracked trade, mark the old trade as 'lost tracking' and remove from
monitoring WITHOUT cancelling orders (they belong to the new position).

This prevents the catastrophic scenario where exit orders are repeatedly cancelled,
leaving positions unprotected.
This commit is contained in:
mindesbunister
2025-10-31 09:34:48 +01:00
parent 37ce94d8f1
commit 8a17c2cf90

View File

@@ -289,6 +289,47 @@ export class PositionManager {
if (position === null || position.size === 0) {
// Position closed externally (by on-chain TP/SL order)
console.log(`⚠️ Position ${trade.symbol} was closed externally (by on-chain order)`)
} else {
// CRITICAL: Verify this position matches the trade we're tracking
// Different entry price means this is a NEW position, not ours
const entryPriceDiff = Math.abs(position.entryPrice - trade.entryPrice)
const entryPriceDiffPercent = (entryPriceDiff / trade.entryPrice) * 100
if (entryPriceDiffPercent > 0.5) {
// Entry prices differ by >0.5% - this is a DIFFERENT position
console.log(`⚠️ Position ${trade.symbol} entry mismatch: tracking $${trade.entryPrice.toFixed(4)} but found $${position.entryPrice.toFixed(4)}`)
console.log(`🗑️ This is a different/newer position - removing old trade from monitoring`)
// Mark the old trade as closed (we lost track of it)
try {
await updateTradeExit({
positionId: trade.positionId,
exitPrice: trade.lastPrice,
exitReason: 'SOFT_SL', // Unknown - just mark as closed
realizedPnL: 0,
exitOrderTx: 'UNKNOWN_CLOSURE',
holdTimeSeconds: Math.floor((Date.now() - trade.entryTime) / 1000),
maxDrawdown: 0,
maxGain: trade.peakPnL,
})
console.log(`💾 Old trade marked as closed (lost tracking)`)
} catch (dbError) {
console.error('❌ Failed to save lost trade closure:', dbError)
}
// Remove from monitoring WITHOUT cancelling orders (they belong to the new position!)
console.log(`🗑️ Removing old trade WITHOUT cancelling orders`)
this.activeTrades.delete(trade.id)
if (this.activeTrades.size === 0 && this.isMonitoring) {
this.stopMonitoring()
}
return
}
}
if (position === null || position.size === 0) {
// Save currentSize before it becomes 0
const sizeBeforeClosure = trade.currentSize