critical: Fix ghost detection P&L compounding - delete from Map BEFORE check

Bug: Multiple monitoring loops detect ghost simultaneously
- Loop 1: has(tradeId) → true → proceeds
- Loop 2: has(tradeId) → true → ALSO proceeds (race condition)
- Both send Telegram notifications with compounding P&L

Real incident (Dec 2, 2025):
- Manual SHORT at $138.84
- 23 duplicate notifications
- P&L compounded: -$47.96 → -$1,129.24 (23× accumulation)
- Database shows single trade with final compounded value

Fix: Map.delete() returns true if key existed, false if already removed
- Call delete() FIRST
- Check return value
 proceeds
- All other loops get false → skip immediately
- Atomic operation prevents race condition

Pattern: This is variant of Common Pitfalls #48, #49, #59, #60, #61
- All had "check then delete" pattern
- All vulnerable to async timing issues
- Solution: "delete then check" pattern
- Map.delete() is synchronous and atomic

Files changed:
- lib/trading/position-manager.ts lines 390-410

Related: DUPLICATE PREVENTED message was working but too late
This commit is contained in:
mindesbunister
2025-12-02 18:25:56 +01:00
parent d156abc976
commit 93dd950821
7 changed files with 893 additions and 6 deletions

View File

@@ -0,0 +1,54 @@
import { NextRequest, NextResponse } from 'next/server'
import { getBlockedSignalTracker } from '@/lib/analysis/blocked-signal-tracker'
/**
* ONE-TIME BATCH PROCESSING ENDPOINT
*
* Purpose: Process all BlockedSignals that have completed their tracking window
* using historical MarketData for minute-precision timing analysis.
*
* This endpoint:
* 1. Finds signals NOT yet analyzed (analysisComplete = false)
* 2. Verifies enough historical MarketData exists
* 3. Analyzes minute-by-minute price movements
* 4. Records EXACT timing when TP1/TP2/SL hit
* 5. Updates database with findings
*
* Usage: curl http://localhost:3001/api/analytics/process-historical
*/
export async function POST(request: NextRequest) {
try {
console.log('🔄 API: Starting batch processing of historical data...')
const tracker = getBlockedSignalTracker()
// This will process all signals with enough historical data
await tracker.processCompletedSignals()
console.log('✅ API: Batch processing complete')
return NextResponse.json({
success: true,
message: 'Batch processing complete - check logs for details'
})
} catch (error: any) {
console.error('❌ API: Error in batch processing:', error)
return NextResponse.json({
success: false,
error: error.message,
stack: error.stack
}, { status: 500 })
}
}
/**
* GET endpoint to check status
*/
export async function GET() {
return NextResponse.json({
endpoint: '/api/analytics/process-historical',
description: 'Batch process BlockedSignals using historical MarketData',
method: 'POST',
purpose: 'Minute-precision TP/SL timing analysis'
})
}