diff --git a/app/api/ai-analytics/route.js b/app/api/ai-analytics/route.js index 50f73a9..82bb399 100644 --- a/app/api/ai-analytics/route.js +++ b/app/api/ai-analytics/route.js @@ -1,260 +1,146 @@ -import { NextResponse } from 'next/server'; -import { PrismaClient } from '@prisma/client'; +import { NextResponse } from 'next/server' +import { PrismaClient } from '@prisma/client' -/** - * AI Learning Analytics API - * - * Provides real-time statistics about AI learning improvements and trading performance - */ +const prisma = new PrismaClient() -const prisma = new PrismaClient(); - -export async function GET(request) { +export async function GET() { try { - const startDate = new Date('2025-07-24'); // When AI trading started + console.log('๐Ÿ” AI Analytics API called') - // Get learning data - const learningData = await prisma.aILearningData.findMany({ + // Calculate date range for analytics (last 30 days) + const endDate = new Date() + const startDate = new Date() + startDate.setDate(startDate.getDate() - 30) + + // Get learning data using correct snake_case model name + const learningData = await prisma.ai_learning_data.findMany({ where: { createdAt: { gte: startDate } }, - orderBy: { createdAt: 'asc' } - }); - - // Get trade data - const tradeData = await prisma.trade.findMany({ - where: { - createdAt: { - gte: startDate - }, - isAutomated: true - }, - orderBy: { createdAt: 'asc' } - }); - - // Get automation sessions - const automationSessions = await prisma.automationSession.findMany({ - where: { - createdAt: { - gte: startDate - } - }, - orderBy: { createdAt: 'desc' } - }); - - // Calculate improvements - const improvements = calculateImprovements(learningData); - const pnlAnalysis = calculatePnLAnalysis(tradeData); - - // Add real-time drift position data - let currentPosition = null; - try { - const HttpUtil = require('../../../lib/http-util'); - const positionData = await HttpUtil.get('http://localhost:9001/api/automation/position-monitor'); - - if (positionData.success && positionData.monitor) { - currentPosition = { - hasPosition: positionData.monitor.hasPosition, - symbol: positionData.monitor.position?.symbol, - side: positionData.monitor.position?.side, - size: positionData.monitor.position?.size, - entryPrice: positionData.monitor.position?.entryPrice, - currentPrice: positionData.monitor.position?.currentPrice, - unrealizedPnl: positionData.monitor.position?.unrealizedPnl, - distanceFromStopLoss: positionData.monitor.stopLossProximity?.distancePercent, - riskLevel: positionData.monitor.riskLevel, - aiRecommendation: positionData.monitor.recommendation - }; - } - } catch (positionError) { - console.log('Could not fetch position data:', positionError.message); - } - - // Build response - const now = new Date(); - const daysSinceStart = Math.ceil((now.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)); - - const response = { - generated: now.toISOString(), - period: { - start: startDate.toISOString(), - end: now.toISOString(), - daysActive: daysSinceStart - }, - overview: { - totalLearningRecords: learningData.length, - totalTrades: tradeData.length, - totalSessions: automationSessions.length, - activeSessions: automationSessions.filter(s => s.status === 'ACTIVE').length - }, - improvements, - pnl: pnlAnalysis, - currentPosition, - realTimeMetrics: { - daysSinceAIStarted: daysSinceStart, - learningRecordsPerDay: Number((learningData.length / daysSinceStart).toFixed(1)), - tradesPerDay: Number((tradeData.length / daysSinceStart).toFixed(1)), - lastUpdate: now.toISOString(), - isLearningActive: automationSessions.filter(s => s.status === 'ACTIVE').length > 0 - }, - learningProof: { - hasImprovement: improvements?.confidenceImprovement > 0, - improvementDirection: improvements?.trend, - confidenceChange: improvements?.confidenceImprovement, - accuracyChange: improvements?.accuracyImprovement, - sampleSize: learningData.length, - isStatisticallySignificant: learningData.length > 100 - } - }; - - return NextResponse.json(response); - - } catch (error) { - console.error('Error generating AI analytics:', error); - return NextResponse.json({ - error: 'Failed to generate analytics', - details: error.message - }, { status: 500 }); - } finally { - await prisma.$disconnect(); - } -} - -function calculateImprovements(learningData) { - if (learningData.length < 10) { - return { - improvement: 0, - trend: 'INSUFFICIENT_DATA', - message: 'Need more learning data to calculate improvements', - confidenceImprovement: 0, - accuracyImprovement: null - }; - } - - // Split data into early vs recent periods - const midPoint = Math.floor(learningData.length / 2); - const earlyData = learningData.slice(0, midPoint); - const recentData = learningData.slice(midPoint); - - // Calculate average confidence scores - const earlyConfidence = getAverageConfidence(earlyData); - const recentConfidence = getAverageConfidence(recentData); - - // Calculate accuracy if outcomes are available - const earlyAccuracy = getAccuracy(earlyData); - const recentAccuracy = getAccuracy(recentData); - - const confidenceImprovement = ((recentConfidence - earlyConfidence) / earlyConfidence) * 100; - const accuracyImprovement = earlyAccuracy && recentAccuracy ? - ((recentAccuracy - earlyAccuracy) / earlyAccuracy) * 100 : null; - - return { - confidenceImprovement: Number(confidenceImprovement.toFixed(2)), - accuracyImprovement: accuracyImprovement ? Number(accuracyImprovement.toFixed(2)) : null, - earlyPeriod: { - samples: earlyData.length, - avgConfidence: Number(earlyConfidence.toFixed(2)), - accuracy: earlyAccuracy ? Number(earlyAccuracy.toFixed(2)) : null - }, - recentPeriod: { - samples: recentData.length, - avgConfidence: Number(recentConfidence.toFixed(2)), - accuracy: recentAccuracy ? Number(recentAccuracy.toFixed(2)) : null - }, - trend: confidenceImprovement > 5 ? 'IMPROVING' : - confidenceImprovement < -5 ? 'DECLINING' : 'STABLE' - }; -} - -function calculatePnLAnalysis(tradeData) { - const analysis = { - totalTrades: tradeData.length, - totalPnL: 0, - totalPnLPercent: 0, - winningTrades: 0, - losingTrades: 0, - breakEvenTrades: 0, - avgTradeSize: 0, - winRate: 0, - avgWin: 0, - avgLoss: 0, - profitFactor: 0 - }; - - if (tradeData.length === 0) { - return analysis; - } - - let totalProfit = 0; - let totalLoss = 0; - let totalAmount = 0; - - tradeData.forEach(trade => { - const pnl = trade.profit || 0; - const pnlPercent = trade.pnlPercent || 0; - const amount = trade.amount || 0; - - analysis.totalPnL += pnl; - analysis.totalPnLPercent += pnlPercent; - totalAmount += amount; - - if (pnl > 0) { - analysis.winningTrades++; - totalProfit += pnl; - } else if (pnl < 0) { - analysis.losingTrades++; - totalLoss += Math.abs(pnl); - } else { - analysis.breakEvenTrades++; - } - }); - - analysis.avgTradeSize = totalAmount / tradeData.length; - analysis.winRate = (analysis.winningTrades / tradeData.length) * 100; - analysis.avgWin = analysis.winningTrades > 0 ? totalProfit / analysis.winningTrades : 0; - analysis.avgLoss = analysis.losingTrades > 0 ? totalLoss / analysis.losingTrades : 0; - analysis.profitFactor = analysis.avgLoss > 0 ? analysis.avgWin / analysis.avgLoss : 0; - - // Round numbers - Object.keys(analysis).forEach(key => { - if (typeof analysis[key] === 'number') { - analysis[key] = Number(analysis[key].toFixed(4)); - } - }); - - return analysis; -} - -function getAverageConfidence(data) { - const confidenceScores = data - .map(d => { - // Handle confidence stored as percentage (75.0) vs decimal (0.75) - let confidence = d.confidenceScore || d.analysisData?.confidence || 0.5; - if (confidence > 1) { - confidence = confidence / 100; // Convert percentage to decimal - } - return confidence; + orderBy: { createdAt: 'desc' }, + take: 1000 }) - .filter(score => score > 0); - - return confidenceScores.length > 0 ? - confidenceScores.reduce((a, b) => a + b, 0) / confidenceScores.length : 0.5; -} -function getAccuracy(data) { - const withOutcomes = data.filter(d => d.outcome && d.accuracyScore); - if (withOutcomes.length === 0) return null; + // Get trade data + const trades = await prisma.trades.findMany({ + where: { + createdAt: { + gte: startDate + } + }, + orderBy: { createdAt: 'desc' }, + take: 100 + }) - const avgAccuracy = withOutcomes.reduce((sum, d) => sum + (d.accuracyScore || 0), 0) / withOutcomes.length; - return avgAccuracy; -} + // Get automation sessions + const sessions = await prisma.automation_sessions.findMany({ + where: { + createdAt: { + gte: startDate + } + }, + orderBy: { createdAt: 'desc' }, + take: 50 + }) -export async function POST(request) { - return NextResponse.json({ - success: true, - message: 'Analytics refreshed', - timestamp: new Date().toISOString() - }); + // Calculate analytics + const overview = { + totalLearningRecords: learningData.length, + totalTrades: trades.length, + totalSessions: sessions.length, + activeSessions: sessions.filter(s => s.status === 'ACTIVE').length + } + + // Calculate improvements + const recentData = learningData.slice(0, Math.floor(learningData.length / 2)) + const olderData = learningData.slice(Math.floor(learningData.length / 2)) + + const recentAvgConfidence = recentData.length > 0 + ? recentData.reduce((sum, d) => sum + (d.confidenceScore || 50), 0) / recentData.length + : 50 + const olderAvgConfidence = olderData.length > 0 + ? olderData.reduce((sum, d) => sum + (d.confidenceScore || 50), 0) / olderData.length + : 50 + + const improvements = { + confidenceImprovement: recentAvgConfidence - olderAvgConfidence, + accuracyImprovement: null, // Would need actual outcome tracking + trend: recentAvgConfidence > olderAvgConfidence ? 'improving' : 'declining' + } + + // Calculate P&L from trades + const completedTrades = trades.filter(t => t.status === 'COMPLETED') + const totalPnL = completedTrades.reduce((sum, t) => sum + (t.profit || 0), 0) + const winningTrades = completedTrades.filter(t => (t.profit || 0) > 0) + const winRate = completedTrades.length > 0 ? winningTrades.length / completedTrades.length : 0 + + const pnl = { + totalTrades: completedTrades.length, + totalPnL: totalPnL, + totalPnLPercent: 0, // Would need to calculate based on initial capital + winRate: winRate, + avgTradeSize: completedTrades.length > 0 + ? completedTrades.reduce((sum, t) => sum + (t.amount || 0), 0) / completedTrades.length + : 0 + } + + // Get current position (if any) + const latestTrade = trades.find(t => t.status === 'ACTIVE' || t.status === 'PENDING') + const currentPosition = latestTrade ? { + symbol: latestTrade.symbol, + side: latestTrade.side, + amount: latestTrade.amount, + entryPrice: latestTrade.price, + unrealizedPnL: 0 // Would need current market price to calculate + } : null + + // Real-time metrics + const firstLearningRecord = learningData[learningData.length - 1] + const daysSinceStart = firstLearningRecord + ? Math.ceil((Date.now() - new Date(firstLearningRecord.createdAt).getTime()) / (1000 * 60 * 60 * 24)) + : 0 + + const realTimeMetrics = { + daysSinceAIStarted: daysSinceStart, + learningRecordsPerDay: daysSinceStart > 0 ? learningData.length / daysSinceStart : 0, + tradesPerDay: daysSinceStart > 0 ? trades.length / daysSinceStart : 0, + lastUpdate: new Date().toISOString(), + isLearningActive: sessions.some(s => s.status === 'ACTIVE') + } + + // Learning proof + const learningProof = { + hasImprovement: improvements.confidenceImprovement > 0, + improvementDirection: improvements.trend, + confidenceChange: improvements.confidenceImprovement, + sampleSize: learningData.length, + isStatisticallySignificant: learningData.length > 50 && Math.abs(improvements.confidenceImprovement) > 5 + } + + const analytics = { + generated: new Date().toISOString(), + overview, + improvements, + pnl, + currentPosition, + realTimeMetrics, + learningProof + } + + console.log('โœ… AI Analytics generated successfully') + return NextResponse.json({ + success: true, + data: analytics + }) + + } catch (error) { + console.error('Error generating AI analytics:', error) + return NextResponse.json({ + success: false, + error: 'Failed to generate AI analytics', + details: error.message + }, { status: 500 }) + } } diff --git a/app/api/automation/analysis-details/route-clean.js b/app/api/automation/analysis-details/route-clean.js.disabled similarity index 100% rename from app/api/automation/analysis-details/route-clean.js rename to app/api/automation/analysis-details/route-clean.js.disabled diff --git a/app/api/automation/analysis-details/route-fixed.js b/app/api/automation/analysis-details/route-fixed.js.disabled similarity index 100% rename from app/api/automation/analysis-details/route-fixed.js rename to app/api/automation/analysis-details/route-fixed.js.disabled diff --git a/app/api/automation/analysis-details/route.js b/app/api/automation/analysis-details/route.js index ab9a6c1..c62d5e3 100644 --- a/app/api/automation/analysis-details/route.js +++ b/app/api/automation/analysis-details/route.js @@ -7,7 +7,7 @@ export async function GET() { try { console.log('โœ… API CORRECTED: Loading with fixed trade calculations...') - const sessions = await prisma.automationSession.findMany({ + const sessions = await prisma.automation_sessions.findMany({ where: { userId: 'default-user', symbol: 'SOLUSD' @@ -32,7 +32,7 @@ export async function GET() { } }) - const recentTrades = await prisma.trade.findMany({ + const recentTrades = await prisma.trades.findMany({ where: { userId: latestSession.userId, symbol: latestSession.symbol diff --git a/app/api/batch-analysis/route.js b/app/api/batch-analysis/route.js index beea07f..0d88f49 100644 --- a/app/api/batch-analysis/route.js +++ b/app/api/batch-analysis/route.js @@ -21,7 +21,7 @@ async function storeAnalysisForLearning(symbol, analysis) { timestamp: new Date().toISOString() } - await prisma.aILearningData.create({ + await prisma.ai_learning_data.create({ data: { userId: 'default-user', // Use same default user as ai-learning-status symbol: symbol, @@ -198,9 +198,7 @@ export async function POST(request) { try { if (allScreenshots.length === 1) { - // Use enhanced AI analysis with symbol and primary timeframe for learning - const primaryTimeframe = timeframes[0] || '1h'; - analysis = await aiAnalysisService.analyzeScreenshot(allScreenshots[0], symbol, primaryTimeframe) + analysis = await aiAnalysisService.analyzeScreenshot(allScreenshots[0]) } else { analysis = await aiAnalysisService.analyzeMultipleScreenshots(allScreenshots) } diff --git a/check-learning-data.js b/check-learning-data.js index 9f892c8..205d0b8 100644 --- a/check-learning-data.js +++ b/check-learning-data.js @@ -5,7 +5,7 @@ async function checkLearningData() { try { console.log('๐Ÿ” Checking AI learning data in database...'); - const learningData = await prisma.aILearningData.findMany({ + const learningData = await prisma.ai_learning_data.findMany({ orderBy: { createdAt: 'desc' }, take: 5 }); @@ -47,7 +47,7 @@ async function checkLearningData() { } }; - const sampleRecord = await prisma.aILearningData.create({ + const sampleRecord = await prisma.ai_learning_data.create({ data: { userId: 'demo-user', analysis: sampleAnalysis.reasoning, diff --git a/lib/ai-learning-status.ts b/lib/ai-learning-status.ts index c6a008c..046ea96 100644 --- a/lib/ai-learning-status.ts +++ b/lib/ai-learning-status.ts @@ -20,13 +20,13 @@ export interface AILearningStatus { export async function getAILearningStatus(userId: string): Promise { try { // Get learning data - const learningData = await prisma.aILearningData.findMany({ + const learningData = await prisma.ai_learning_data.findMany({ where: { userId }, orderBy: { createdAt: 'desc' } }) // Get trade data - use real database data instead of demo numbers - const trades = await prisma.trade.findMany({ + const trades = await prisma.trades.findMany({ where: { userId, // isAutomated: true // This field might not exist in current schema diff --git a/show-learning-proof.js b/show-learning-proof.js index 2059a8d..f8c2ec7 100644 --- a/show-learning-proof.js +++ b/show-learning-proof.js @@ -5,7 +5,7 @@ async function showDetailedLearningData() { try { console.log('๐Ÿ” Detailed AI Learning Data Analysis...\n'); - const learningData = await prisma.aILearningData.findMany({ + const learningData = await prisma.ai_learning_data.findMany({ orderBy: { createdAt: 'desc' }, take: 3 }); diff --git a/test-drift-feedback-loop.js b/test-drift-feedback-loop.js index 463e3cc..6963f2d 100644 --- a/test-drift-feedback-loop.js +++ b/test-drift-feedback-loop.js @@ -3,9 +3,11 @@ /** * Test Drift Feedback Loop System * Comprehensive test of the real-trade learning feedback system - */ - -async function testDriftFeedbackLoop() { + * const learningRecords = await prisma.ai_learning_data.findMany({ + where: { userId: 'default-user' }, + orderBy: { createdAt: 'desc' }, + take: 5 + });c function testDriftFeedbackLoop() { console.log('๐Ÿงช TESTING DRIFT FEEDBACK LOOP SYSTEM') console.log('='.repeat(60))