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:
@@ -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)')
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user