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
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
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'
|
|
})
|
|
}
|