/** * Blocked Signal Tracking Status API * * GET: View tracking status and statistics * POST: Manually trigger tracking update (requires auth) */ import { NextRequest, NextResponse } from 'next/server' import { getPrismaClient } from '@/lib/database/trades' import { getBlockedSignalTracker } from '@/lib/analysis/blocked-signal-tracker' // GET: View tracking status export async function GET(request: NextRequest) { try { const prisma = getPrismaClient() // Get tracking statistics const total = await prisma.blockedSignal.count({ where: { blockReason: 'DATA_COLLECTION_ONLY' } }) const incomplete = await prisma.blockedSignal.count({ where: { blockReason: 'DATA_COLLECTION_ONLY', analysisComplete: false } }) const complete = await prisma.blockedSignal.count({ where: { blockReason: 'DATA_COLLECTION_ONLY', analysisComplete: true } }) // Get completion rates by timeframe const byTimeframe = await prisma.blockedSignal.groupBy({ by: ['timeframe'], where: { blockReason: 'DATA_COLLECTION_ONLY' }, _count: { id: true } }) // Get signals with price data const withPriceData = await prisma.blockedSignal.count({ where: { blockReason: 'DATA_COLLECTION_ONLY', priceAfter1Min: { not: null } } }) // Get TP/SL hit rates const tp1Hits = await prisma.blockedSignal.count({ where: { blockReason: 'DATA_COLLECTION_ONLY', wouldHitTP1: true } }) const slHits = await prisma.blockedSignal.count({ where: { blockReason: 'DATA_COLLECTION_ONLY', wouldHitSL: true } }) // Get recent tracked signals const recentSignals = await prisma.blockedSignal.findMany({ where: { blockReason: 'DATA_COLLECTION_ONLY' }, select: { id: true, timeframe: true, symbol: true, direction: true, signalQualityScore: true, priceAfter1Min: true, priceAfter5Min: true, priceAfter15Min: true, priceAfter30Min: true, wouldHitTP1: true, wouldHitTP2: true, wouldHitSL: true, analysisComplete: true, createdAt: true }, orderBy: { createdAt: 'desc' }, take: 10 }) return NextResponse.json({ success: true, tracking: { total, complete, incomplete, completionRate: total > 0 ? ((complete / total) * 100).toFixed(1) : '0.0' }, byTimeframe: byTimeframe.map(tf => ({ timeframe: tf.timeframe, count: tf._count.id })), metrics: { withPriceData, tp1Hits, slHits, tp1HitRate: complete > 0 ? ((tp1Hits / complete) * 100).toFixed(1) : '0.0', slHitRate: complete > 0 ? ((slHits / complete) * 100).toFixed(1) : '0.0' }, recentSignals: recentSignals.map((signal: any) => ({ id: signal.id, timeframe: `${signal.timeframe}min`, symbol: signal.symbol, direction: signal.direction, quality: signal.signalQualityScore, price1min: signal.priceAfter1Min, price5min: signal.priceAfter5Min, price15min: signal.priceAfter15Min, price30min: signal.priceAfter30Min, hitTP1: signal.wouldHitTP1, hitTP2: signal.wouldHitTP2, hitSL: signal.wouldHitSL, complete: signal.analysisComplete, time: signal.createdAt })) }) } catch (error) { console.error('Error getting signal tracking status:', error) return NextResponse.json( { success: false, error: 'Failed to get tracking status' }, { status: 500 } ) } } // POST: Manually trigger tracking update export async function POST(request: NextRequest) { try { // Check auth const authHeader = request.headers.get('Authorization') const apiKey = process.env.API_SECRET_KEY if (!authHeader || !apiKey || authHeader !== `Bearer ${apiKey}`) { return NextResponse.json( { success: false, error: 'Unauthorized' }, { status: 401 } ) } const tracker = getBlockedSignalTracker() // Trigger manual update by restarting console.log('🔄 Manual tracking update triggered') tracker.stop() tracker.start() return NextResponse.json({ success: true, message: 'Tracking update triggered' }) } catch (error) { console.error('Error triggering tracking update:', error) return NextResponse.json( { success: false, error: 'Failed to trigger update' }, { status: 500 } ) } }