critical: Fix Smart Validation Queue - restore signals from database on startup

Problem: Queue is in-memory only (Map), container restarts lose all queued signals
Impact: Quality 50-89 signals blocked but never validated, missed +8.56 manual entry opportunity
Root Cause: startSmartValidation() just created empty queue, never loaded from database

Fix:
- Query BlockedSignal table for signals within 30-minute entry window
- Re-queue each signal with original parameters
- Start monitoring if any signals restored
- Use console.log() instead of logger.log() for production visibility

Files Changed:
- lib/trading/smart-validation-queue.ts (Lines 456-500, 137-175, 117-127)

Expected Behavior After Fix:
- Container restart: Loads pending signals from database
- Signals within 30min window: Re-queued and monitored
- Monitoring starts immediately if signals exist
- Logs show: '🔄 Restoring N pending signals from database'

User Quote: 'the smart validation system should have entered the trade as it shot up'

This fix ensures the Smart Validation Queue actually works after container restarts,
catching marginal quality signals that confirm direction via price action.

Deploy Status:  DEPLOYED Dec 9, 2025 17:07 CET
This commit is contained in:
mindesbunister
2025-12-09 17:43:02 +01:00
parent 1ecef77807
commit 2a1badf3ab

View File

@@ -111,8 +111,8 @@ class SmartValidationQueue {
}
this.queue.set(signalId, queuedSignal)
logger.log(`⏰ Smart validation queued: ${params.symbol} ${params.direction.toUpperCase()} @ $${params.originalPrice.toFixed(2)} (quality: ${params.qualityScore})`)
logger.log(` Watching for ${queuedSignal.entryWindowMinutes}min: +${queuedSignal.confirmationThreshold}% confirms, ${queuedSignal.maxDrawdown}% abandons`)
console.log(`⏰ Smart validation queued: ${params.symbol} ${params.direction.toUpperCase()} @ $${params.originalPrice.toFixed(2)} (quality: ${params.qualityScore})`)
console.log(` Watching for ${queuedSignal.entryWindowMinutes}min: +${queuedSignal.confirmationThreshold}% confirms, ${queuedSignal.maxDrawdown}% abandons`)
// Send Telegram notification
await sendValidationNotification({
@@ -140,7 +140,7 @@ class SmartValidationQueue {
}
this.isMonitoring = true
logger.log('👁️ Smart validation monitoring started (checks every 30s)')
console.log('👁️ Smart validation monitoring started (checks every 30s)')
// Check every 30 seconds
this.monitoringInterval = setInterval(async () => {
@@ -157,7 +157,7 @@ class SmartValidationQueue {
this.monitoringInterval = undefined
}
this.isMonitoring = false
logger.log('⏸️ Smart validation monitoring stopped')
console.log('⏸️ Smart validation monitoring stopped')
}
/**
@@ -172,7 +172,7 @@ class SmartValidationQueue {
return
}
logger.log(`👁️ Smart validation check: ${pending.length} pending signals`)
console.log(`👁️ Smart validation check: ${pending.length} pending signals`)
for (const signal of pending) {
try {
@@ -453,7 +453,55 @@ export function getSmartValidationQueue(): SmartValidationQueue {
return queueInstance
}
export function startSmartValidation(): void {
export async function startSmartValidation(): Promise<void> {
const queue = getSmartValidationQueue()
logger.log('🧠 Smart validation system ready')
// CRITICAL FIX (Dec 9, 2025): Load pending signals from database on startup
// Bug: Queue is in-memory only, container restart loses all queued signals
// Solution: Query BlockedSignal table for signals within entry window
try {
const { getPrismaClient } = await import('../database/trades')
const prisma = getPrismaClient()
// Find signals blocked within last 30 minutes (entry window)
const thirtyMinutesAgo = new Date(Date.now() - 30 * 60 * 1000)
const recentBlocked = await prisma.blockedSignal.findMany({
where: {
blockReason: 'QUALITY_SCORE_TOO_LOW',
signalQualityScore: { gte: 50, lt: 90 }, // Marginal quality range
createdAt: { gte: thirtyMinutesAgo },
},
orderBy: { createdAt: 'desc' },
})
console.log(`🔄 Restoring ${recentBlocked.length} pending signals from database`)
// Re-queue each signal
for (const signal of recentBlocked) {
await queue.addSignal({
blockReason: 'QUALITY_SCORE_TOO_LOW',
symbol: signal.symbol,
direction: signal.direction as 'long' | 'short',
originalPrice: signal.entryPrice,
qualityScore: signal.signalQualityScore || 0,
atr: signal.atr || undefined,
adx: signal.adx || undefined,
rsi: signal.rsi || undefined,
volumeRatio: signal.volumeRatio || undefined,
pricePosition: signal.pricePosition || undefined,
indicatorVersion: signal.indicatorVersion || 'v5',
timeframe: signal.timeframe || '5',
})
}
if (recentBlocked.length > 0) {
console.log(`✅ Smart validation restored ${recentBlocked.length} signals, monitoring started`)
} else {
console.log('🧠 Smart validation system ready (no pending signals)')
}
} catch (error) {
console.error('❌ Error restoring smart validation queue:', error)
console.log('🧠 Smart validation system ready (error loading signals)')
}
}