Files
trading_bot_v3/app/api/batch-analysis/route.js
mindesbunister f263cac55f Fix: Correct all database model names from camelCase to snake_case
- 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.
2025-07-26 10:53:56 +02:00

318 lines
11 KiB
JavaScript

import { NextResponse } from 'next/server'
import { enhancedScreenshotService } from '../../../lib/enhanced-screenshot'
import { aiAnalysisService } from '../../../lib/ai-analysis'
import { progressTracker } from '../../../lib/progress-tracker'
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Store analysis results for AI learning
async function storeAnalysisForLearning(symbol, analysis) {
try {
console.log('💾 Storing analysis for AI learning...')
// Extract market conditions for learning
const marketConditions = {
marketSentiment: analysis.marketSentiment || 'NEUTRAL',
keyLevels: analysis.keyLevels || {},
trends: analysis.trends || {},
timeframes: ['5m', '15m', '30m'], // Multi-timeframe analysis
timestamp: new Date().toISOString()
}
await prisma.ai_learning_data.create({
data: {
userId: 'default-user', // Use same default user as ai-learning-status
symbol: symbol,
timeframe: 'MULTI', // Indicates multi-timeframe batch analysis
analysisData: JSON.stringify(analysis),
marketConditions: JSON.stringify(marketConditions),
confidenceScore: Math.round(analysis.confidence || 50),
createdAt: new Date()
}
})
console.log(`✅ Analysis stored for learning: ${symbol} - ${analysis.recommendation || 'HOLD'} (${analysis.confidence || 50}% confidence)`)
} catch (error) {
console.error('❌ Failed to store analysis for learning:', error)
}
}
export async function POST(request) {
try {
const body = await request.json()
const { symbol, layouts, timeframes, selectedLayouts, analyze = true } = body
console.log('📊 Batch analysis request:', { symbol, layouts, timeframes, selectedLayouts, analyze })
// Validate inputs
if (!symbol || !timeframes || !Array.isArray(timeframes) || timeframes.length === 0) {
return NextResponse.json(
{ success: false, error: 'Invalid request: symbol and timeframes array required' },
{ status: 400 }
)
}
// Generate unique session ID for progress tracking
const sessionId = `batch_analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
console.log('🔍 Created batch analysis session ID:', sessionId)
// Create progress tracking session with initial steps
const initialSteps = [
{
id: 'init',
title: 'Initializing Batch Analysis',
description: 'Starting multi-timeframe analysis...',
status: 'pending'
},
{
id: 'auth',
title: 'TradingView Authentication',
description: 'Logging into TradingView accounts',
status: 'pending'
},
{
id: 'navigation',
title: 'Chart Navigation',
description: 'Navigating to chart layouts',
status: 'pending'
},
{
id: 'loading',
title: 'Chart Data Loading',
description: 'Waiting for chart data and indicators',
status: 'pending'
},
{
id: 'capture',
title: 'Screenshot Capture',
description: `Capturing screenshots for ${timeframes.length} timeframes`,
status: 'pending'
},
{
id: 'analysis',
title: 'AI Analysis',
description: 'Analyzing all screenshots with AI',
status: 'pending'
}
]
// Create the progress session
progressTracker.createSession(sessionId, initialSteps)
// Prepare base configuration
const baseConfig = {
symbol: symbol || 'BTCUSD',
layouts: layouts || selectedLayouts || ['ai', 'diy'],
sessionId,
credentials: {
email: process.env.TRADINGVIEW_EMAIL,
password: process.env.TRADINGVIEW_PASSWORD
}
}
console.log('🔧 Base config:', baseConfig)
let allScreenshots = []
const screenshotResults = []
try {
// STEP 1: Collect ALL screenshots from ALL timeframes FIRST
console.log(`🔄 Starting batch screenshot collection for ${timeframes.length} timeframes...`)
progressTracker.updateStep(sessionId, 'init', 'active', 'Starting batch screenshot collection...')
for (let i = 0; i < timeframes.length; i++) {
const timeframe = timeframes[i]
const timeframeLabel = getTimeframeLabel(timeframe)
console.log(`📸 Collecting screenshots for ${symbol} ${timeframeLabel} (${i + 1}/${timeframes.length})`)
// Update progress for current timeframe
progressTracker.updateStep(sessionId, 'capture', 'active',
`Capturing ${timeframeLabel} screenshots (${i + 1}/${timeframes.length})`
)
try {
const config = {
...baseConfig,
timeframe: timeframe,
sessionId: i === 0 ? sessionId : undefined // Only track progress for first timeframe
}
// Capture screenshots WITHOUT analysis
const screenshots = await enhancedScreenshotService.captureWithLogin(config)
if (screenshots && screenshots.length > 0) {
console.log(`✅ Captured ${screenshots.length} screenshots for ${timeframeLabel}`)
// Store screenshots with metadata
const screenshotData = {
timeframe: timeframe,
timeframeLabel: timeframeLabel,
screenshots: screenshots,
success: true
}
screenshotResults.push(screenshotData)
allScreenshots.push(...screenshots)
} else {
console.warn(`⚠️ No screenshots captured for ${timeframeLabel}`)
screenshotResults.push({
timeframe: timeframe,
timeframeLabel: timeframeLabel,
screenshots: [],
success: false,
error: 'No screenshots captured'
})
}
} catch (timeframeError) {
console.error(`❌ Error capturing ${timeframeLabel}:`, timeframeError)
screenshotResults.push({
timeframe: timeframe,
timeframeLabel: timeframeLabel,
screenshots: [],
success: false,
error: timeframeError.message
})
}
// Small delay between captures
if (i < timeframes.length - 1) {
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
console.log(`📊 Batch screenshot collection completed: ${allScreenshots.length} total screenshots`)
progressTracker.updateStep(sessionId, 'capture', 'completed', `Captured ${allScreenshots.length} total screenshots`)
// STEP 2: Send ALL screenshots to AI for comprehensive analysis
let analysis = null
if (analyze && allScreenshots.length > 0) {
console.log(`🤖 Starting comprehensive AI analysis on ${allScreenshots.length} screenshots...`)
progressTracker.updateStep(sessionId, 'analysis', 'active', 'Running comprehensive AI analysis...')
try {
if (allScreenshots.length === 1) {
analysis = await aiAnalysisService.analyzeScreenshot(allScreenshots[0])
} else {
analysis = await aiAnalysisService.analyzeMultipleScreenshots(allScreenshots)
}
if (analysis) {
console.log('✅ Comprehensive AI analysis completed')
progressTracker.updateStep(sessionId, 'analysis', 'completed', 'AI analysis completed successfully!')
// Store analysis for learning
await storeAnalysisForLearning(symbol, analysis)
} else {
throw new Error('AI analysis returned null')
}
} catch (analysisError) {
console.error('❌ AI analysis failed:', analysisError)
progressTracker.updateStep(sessionId, 'analysis', 'error', `AI analysis failed: ${analysisError.message}`)
// Don't fail the entire request - return screenshots without analysis
analysis = null
}
}
// STEP 3: Format comprehensive results
const result = {
success: true,
type: 'batch_analysis',
sessionId,
timestamp: Date.now(),
symbol: symbol,
timeframes: timeframes,
layouts: baseConfig.layouts,
summary: `Batch analysis completed for ${timeframes.length} timeframes`,
totalScreenshots: allScreenshots.length,
screenshotResults: screenshotResults,
allScreenshots: allScreenshots.map(path => ({
url: `/screenshots/${path.split('/').pop()}`,
timestamp: Date.now()
})),
analysis: analysis, // Comprehensive analysis of ALL screenshots
message: `Successfully captured ${allScreenshots.length} screenshots${analysis ? ' with comprehensive AI analysis' : ''}`
}
// Clean up session
setTimeout(() => progressTracker.deleteSession(sessionId), 2000)
// Trigger post-analysis cleanup in development mode
if (process.env.NODE_ENV === 'development') {
try {
const { default: aggressiveCleanup } = await import('../../../lib/aggressive-cleanup')
// Run cleanup in background, don't block the response
aggressiveCleanup.runPostAnalysisCleanup().catch(console.error)
} catch (cleanupError) {
console.error('Error triggering post-batch-analysis cleanup:', cleanupError)
}
}
return NextResponse.json(result)
} catch (error) {
console.error('❌ Batch analysis failed:', error)
progressTracker.updateStep(sessionId, 'analysis', 'error', `Batch analysis failed: ${error.message}`)
setTimeout(() => progressTracker.deleteSession(sessionId), 5000)
return NextResponse.json(
{
success: false,
error: 'Batch analysis failed',
message: error.message,
sessionId: sessionId
},
{ status: 500 }
)
}
} catch (error) {
console.error('Batch analysis API error:', error)
return NextResponse.json(
{
success: false,
error: 'Batch analysis failed',
message: error.message
},
{ status: 500 }
)
}
}
// Helper function to get timeframe label
function getTimeframeLabel(timeframe) {
const timeframes = [
{ label: '1m', value: '1' },
{ label: '5m', value: '5' },
{ label: '15m', value: '15' },
{ label: '30m', value: '30' },
{ label: '1h', value: '60' },
{ label: '2h', value: '120' },
{ label: '4h', value: '240' },
{ label: '1d', value: 'D' },
{ label: '1w', value: 'W' },
{ label: '1M', value: 'M' },
]
return timeframes.find(t => t.value === timeframe)?.label || timeframe
}
export async function GET() {
return NextResponse.json({
message: 'Batch Analysis API - use POST method for multi-timeframe analysis',
endpoints: {
POST: '/api/batch-analysis - Run multi-timeframe analysis with parameters'
}
})
}