Implement batch comparative analysis for multi-timeframe

- Create new /api/batch-analysis endpoint for collecting all screenshots first
- Modified AIAnalysisPanel to use batch analysis for multiple timeframes
- All screenshots captured before AI analysis (no immediate analysis per timeframe)
- Enables AI to compare across timeframes for better trend analysis
- Maintains UI compatibility with existing display logic
This commit is contained in:
mindesbunister
2025-07-17 14:21:51 +02:00
parent abbabe7e8d
commit 8688151239
2 changed files with 232 additions and 55 deletions

View File

@@ -0,0 +1,185 @@
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,
timeframes = [],
layouts = ['ai'],
sessionId: providedSessionId
} = body
console.log('🎯 Batch analysis request:', { symbol, timeframes, layouts })
// Use provided sessionId or generate one
const sessionId = providedSessionId || `batch_analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
console.log('🔍 Using batch session ID:', sessionId)
// Create progress tracking with batch-specific steps
const totalCaptures = timeframes.length * layouts.length
const initialSteps = [
{
id: 'init',
title: 'Initializing Batch Analysis',
description: `Preparing to capture ${totalCaptures} screenshots across ${timeframes.length} timeframes`,
status: 'pending'
},
{
id: 'auth',
title: 'TradingView Authentication',
description: 'Logging into TradingView accounts',
status: 'pending'
},
{
id: 'batch_capture',
title: 'Batch Screenshot Capture',
description: `Capturing screenshots for all ${timeframes.length} timeframes`,
status: 'pending'
},
{
id: 'comparative_analysis',
title: 'Comparative AI Analysis',
description: `Analyzing all ${totalCaptures} screenshots together for timeframe comparison`,
status: 'pending'
}
]
// Create the progress session
progressTracker.createSession(sessionId, initialSteps)
let allScreenshots = []
const timeframeResults = []
try {
// Mark init as completed
progressTracker.updateStep(sessionId, 'init', 'completed', 'Batch analysis initialized')
progressTracker.updateStep(sessionId, 'auth', 'active', 'Starting authentication...')
// Capture screenshots for each timeframe WITHOUT analysis
for (let i = 0; i < timeframes.length; i++) {
const timeframe = timeframes[i]
console.log(`📸 Capturing ${timeframe} screenshots (${i + 1}/${timeframes.length})...`)
// Update progress
progressTracker.updateStep(sessionId, 'batch_capture', 'active',
`Capturing ${timeframe} screenshots (${i + 1}/${timeframes.length})`)
const config = {
symbol: symbol || 'BTCUSD',
timeframe: timeframe,
layouts: layouts,
sessionId: `${sessionId}_tf_${timeframe}`, // Sub-session for this timeframe
credentials: {
email: process.env.TRADINGVIEW_EMAIL,
password: process.env.TRADINGVIEW_PASSWORD
}
}
try {
// Capture screenshots only (no analysis)
const screenshots = await enhancedScreenshotService.captureWithLogin(config)
allScreenshots.push(...screenshots)
timeframeResults.push({
timeframe,
screenshots: screenshots.length,
files: screenshots
})
console.log(`${timeframe}: ${screenshots.length} screenshots captured`)
} catch (error) {
console.error(`❌ Failed to capture ${timeframe}:`, error)
timeframeResults.push({
timeframe,
error: error.message,
screenshots: 0,
files: []
})
}
}
// Mark capture as completed
progressTracker.updateStep(sessionId, 'batch_capture', 'completed',
`All timeframes captured: ${allScreenshots.length} total screenshots`)
// Now perform comparative analysis on ALL screenshots
console.log(`🤖 Starting comparative analysis of ${allScreenshots.length} screenshots...`)
progressTracker.updateStep(sessionId, 'comparative_analysis', 'active',
`Analyzing ${allScreenshots.length} screenshots for timeframe comparison`)
let analysis = null
if (allScreenshots.length > 0) {
try {
// Use the analyzeMultipleScreenshots method for comparative analysis
analysis = await aiAnalysisService.analyzeMultipleScreenshots(allScreenshots)
if (analysis) {
progressTracker.updateStep(sessionId, 'comparative_analysis', 'completed',
'Comparative analysis completed successfully!')
} else {
progressTracker.updateStep(sessionId, 'comparative_analysis', 'error',
'Analysis returned no results')
}
} catch (analysisError) {
console.error('❌ Comparative analysis failed:', analysisError)
progressTracker.updateStep(sessionId, 'comparative_analysis', 'error',
`Analysis failed: ${analysisError.message}`)
}
} else {
progressTracker.updateStep(sessionId, 'comparative_analysis', 'error',
'No screenshots available for analysis')
}
// Cleanup session after delay
setTimeout(() => progressTracker.deleteSession(sessionId), 5000)
const result = {
success: true,
sessionId,
type: 'batch_comparative',
symbol: symbol || 'BTCUSD',
timeframes,
layouts,
totalScreenshots: allScreenshots.length,
screenshots: allScreenshots,
timeframeBreakdown: timeframeResults,
analysis,
summary: `Captured ${allScreenshots.length} screenshots across ${timeframes.length} timeframes for comparative analysis`
}
console.log('✅ Batch comparative analysis completed:', {
timeframes: timeframes.length,
screenshots: allScreenshots.length,
hasAnalysis: !!analysis
})
return NextResponse.json(result)
} catch (error) {
console.error('❌ Batch analysis error:', error)
progressTracker.updateStep(sessionId, 'comparative_analysis', 'error',
`Batch analysis failed: ${error.message}`)
return NextResponse.json({
success: false,
error: error.message,
sessionId,
partialResults: {
timeframeResults,
screenshotsCaptured: allScreenshots.length
}
}, { status: 500 })
}
} catch (error) {
console.error('❌ Batch analysis request error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}

View File

@@ -306,68 +306,60 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
onAnalysisComplete(data.analysis, analysisSymbol)
}
} else {
// Multiple timeframe analysis
const results = []
// Multiple timeframe analysis - use batch comparative analysis
console.log(`🎯 Starting batch comparative analysis for ${analysisTimeframes.length} timeframes`)
for (let i = 0; i < analysisTimeframes.length; i++) {
const tf = analysisTimeframes[i]
const timeframeLabel = timeframes.find(t => t.value === tf)?.label || tf
// Pre-generate sessionId for batch analysis
const sessionId = `batch_analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
startProgressTracking(sessionId)
console.log(`🧪 Analyzing timeframe: ${timeframeLabel}`)
const response = await fetch('/api/enhanced-screenshot', {
const response = await fetch('/api/batch-analysis', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
symbol: analysisSymbol,
timeframe: tf,
timeframes: analysisTimeframes,
layouts: selectedLayouts,
analyze: true
sessionId: sessionId
})
})
const result = await response.json()
results.push({
timeframe: tf,
timeframeLabel,
success: response.ok,
result
})
const data = await response.json()
// Start progress tracking for the first timeframe session
if (i === 0 && result.sessionId) {
startProgressTracking(result.sessionId)
if (!response.ok) {
throw new Error(data.error || 'Batch analysis failed')
}
// Update timeframe progress manually for multi-timeframe
setProgress(prev => prev ? {
...prev,
timeframeProgress: {
current: i + 1,
total: analysisTimeframes.length,
currentTimeframe: timeframeLabel
}
} : null)
// Small delay between requests
await new Promise(resolve => setTimeout(resolve, 1000))
}
console.log(`✅ Batch analysis completed: ${data.totalScreenshots} screenshots, ${data.timeframes.length} timeframes`)
// Transform batch result to match expected format for UI compatibility
const multiResult = {
type: 'multi_timeframe',
type: 'batch_comparative',
symbol: analysisSymbol,
summary: `Analyzed ${results.length} timeframes for ${analysisSymbol}`,
results
summary: data.summary || `Batch comparative analysis of ${data.timeframes?.length || analysisTimeframes.length} timeframes`,
analysis: data.analysis,
screenshots: data.screenshots,
timeframeBreakdown: data.timeframeBreakdown,
totalScreenshots: data.totalScreenshots,
timeframes: analysisTimeframes.map(tf => timeframes.find(t => t.value === tf)?.label || tf),
// Create results array for UI compatibility
results: analysisTimeframes.map(tf => ({
timeframe: tf,
timeframeLabel: timeframes.find(t => t.value === tf)?.label || tf,
success: true,
result: {
analysis: data.analysis, // Single comparative analysis for all timeframes
screenshots: data.screenshots.filter((s: string) => s.includes(`_${tf}_`)),
sessionId: sessionId
}
}))
}
setResult(multiResult)
// Call the callback with the first successful analysis result if provided
if (onAnalysisComplete) {
const firstSuccessfulResult = results.find(r => r.success && r.result?.analysis)
if (firstSuccessfulResult) {
onAnalysisComplete(firstSuccessfulResult.result.analysis, analysisSymbol)
}
// Call the callback with analysis result if provided
if (onAnalysisComplete && data.analysis) {
onAnalysisComplete(data.analysis, analysisSymbol)
}
}
} catch (err) {
@@ -967,7 +959,7 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
</div>
)}
{result && result.type === 'multi_timeframe' && (
{result && (result.type === 'multi_timeframe' || result.type === 'batch_comparative') && (
<div className="mt-6 space-y-4">
<div className="flex items-center justify-between">
<h3 className="text-lg font-bold text-white flex items-center">
@@ -1482,7 +1474,7 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
)}
{/* Multi-timeframe Screenshot Gallery */}
{result && result.type === 'multi_timeframe' && result.results && (
{result && (result.type === 'multi_timeframe' || result.type === 'batch_comparative') && result.results && (
<ScreenshotGallery
screenshots={result.results
.filter((r: any) => r.success && r.result.screenshots)