fix: implement proper multi-timeframe batch analysis
- Create /api/batch-analysis endpoint that collects ALL screenshots first - Then sends all screenshots to AI for comprehensive analysis - Fixes issue where individual timeframes were analyzed immediately - Multi-timeframe analysis now provides cross-timeframe consensus - Update AIAnalysisPanel to use batch analysis for multiple timeframes - Maintains backward compatibility with single timeframe analysis
This commit is contained in:
265
app/api/batch-analysis/route.js
Normal file
265
app/api/batch-analysis/route.js
Normal file
@@ -0,0 +1,265 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { enhancedScreenshotService } from '../../../lib/enhanced-screenshot'
|
||||
import { aiAnalysisService } from '../../../lib/ai-analysis'
|
||||
import { progressTracker } from '../../../lib/progress-tracker'
|
||||
|
||||
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 })
|
||||
|
||||
// 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!')
|
||||
} 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)
|
||||
|
||||
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'
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user