- Fixed ai-analytics API: Created missing endpoint and corrected model names - Fixed ai-learning-status.ts: Updated to use ai_learning_data and trades models - Fixed batch-analysis route: Corrected ai_learning_data model references - Fixed analysis-details route: Updated automation_sessions and trades models - Fixed test scripts: Updated model names in check-learning-data.js and others - Disabled conflicting route files to prevent Next.js confusion All APIs now use correct snake_case model names matching Prisma schema: - ai_learning_data (not aILearningData) - automation_sessions (not automationSession) - trades (not trade) This resolves 'Unable to load REAL AI analytics' frontend errors.
147 lines
4.7 KiB
JavaScript
147 lines
4.7 KiB
JavaScript
import { NextResponse } from 'next/server'
|
|
import { PrismaClient } from '@prisma/client'
|
|
|
|
const prisma = new PrismaClient()
|
|
|
|
export async function GET() {
|
|
try {
|
|
console.log('🔍 AI Analytics API called')
|
|
|
|
// 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: 'desc' },
|
|
take: 1000
|
|
})
|
|
|
|
// Get trade data
|
|
const trades = await prisma.trades.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: startDate
|
|
}
|
|
},
|
|
orderBy: { createdAt: 'desc' },
|
|
take: 100
|
|
})
|
|
|
|
// Get automation sessions
|
|
const sessions = await prisma.automation_sessions.findMany({
|
|
where: {
|
|
createdAt: {
|
|
gte: startDate
|
|
}
|
|
},
|
|
orderBy: { createdAt: 'desc' },
|
|
take: 50
|
|
})
|
|
|
|
// 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 })
|
|
}
|
|
}
|