Files
trading_bot_v3/lib/ai-analysis.ts
mindesbunister 4965a3d0af 🤖 Multi-Layout AI Analysis Integration Complete
 Major Achievement:
- Implemented comprehensive multi-screenshot AI analysis
- Both AI and DIY layout screenshots analyzed simultaneously
- Cross-layout comparison for enhanced trading decisions
- Cost-optimized with GPT-4o mini (~0.6 cents per analysis)

🔧 Technical Implementation:
- Added analyzeMultipleScreenshots() method to AIAnalysisService
- Enhanced API to handle single vs multi-screenshot analysis
- Updated UI to display layout comparison insights
- Fixed deprecated gpt-4-vision-preview → gpt-4o-mini

🎯 AI Analysis Features:
- Layout-specific insights (AI Layout vs DIY Module)
- Consensus detection between different chart views
- Divergence analysis for conflicting signals
- Enhanced confidence scoring based on multi-layout agreement
- Comprehensive trading setup with entry/stop/targets

💰 Cost Optimization:
- Switched from GPT-4o (/usr/bin/bash.048/analysis) to GPT-4o mini (/usr/bin/bash.006/analysis)
- 8x cost reduction while maintaining analysis quality
- ~.80/month for 10 daily analyses

🖥️ Enhanced UI Components:
- Multi-layout analysis display sections
- Cross-layout consensus indicators
- Layout comparison visualization
- Enhanced trading setup presentation

📊 Test Results:
- Both AI and DIY screenshots captured successfully
- Multi-layout analysis working flawlessly
- Comprehensive trading recommendations generated
- Entry/stop/target levels provided with rationale

Ready for production trading analysis! 🚀
2025-07-13 17:46:17 +02:00

428 lines
14 KiB
TypeScript

import OpenAI from 'openai'
import fs from 'fs/promises'
import path from 'path'
import { enhancedScreenshotService, ScreenshotConfig } from './enhanced-screenshot'
import { TradingViewCredentials } from './tradingview-automation'
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
})
export interface AnalysisResult {
summary: string
marketSentiment: 'BULLISH' | 'BEARISH' | 'NEUTRAL'
keyLevels: {
support: number[]
resistance: number[]
}
recommendation: 'BUY' | 'SELL' | 'HOLD'
confidence: number // 0-100
reasoning: string
// Enhanced trading analysis (optional)
entry?: {
price: number
buffer?: string
rationale: string
}
stopLoss?: {
price: number
rationale: string
}
takeProfits?: {
tp1?: { price: number; description: string }
tp2?: { price: number; description: string }
}
riskToReward?: string
confirmationTrigger?: string
indicatorAnalysis?: {
rsi?: string
vwap?: string
obv?: string
}
}
export class AIAnalysisService {
async analyzeScreenshot(filename: string): Promise<AnalysisResult | null> {
try {
const screenshotsDir = path.join(process.cwd(), 'screenshots')
const imagePath = path.join(screenshotsDir, filename)
// Read image file
const imageBuffer = await fs.readFile(imagePath)
const base64Image = imageBuffer.toString('base64')
const prompt = `You are a technical chart analysis expert. Please analyze this TradingView chart image and provide objective technical analysis data.
**Important**: This is for educational and research purposes only. Please analyze the technical indicators, price levels, and chart patterns visible in the image.
Examine the chart and identify:
- Current price action and trend direction
- Key support and resistance levels visible on the chart
- Technical indicator readings (RSI, moving averages, volume if visible)
- Chart patterns or formations
- Market structure elements
Provide your analysis in this exact JSON format (replace values with your analysis):
{
"summary": "Objective description of what you observe in the chart",
"marketSentiment": "BULLISH|BEARISH|NEUTRAL",
"keyLevels": {
"support": [list of visible support price levels as numbers],
"resistance": [list of visible resistance price levels as numbers]
},
"recommendation": "BUY|SELL|HOLD",
"confidence": 75,
"reasoning": "Technical analysis reasoning based on indicators and price action",
"entry": {
"price": 150.50,
"buffer": "±0.25",
"rationale": "Technical reasoning for entry level"
},
"stopLoss": {
"price": 148.00,
"rationale": "Technical reasoning for stop level"
},
"takeProfits": {
"tp1": { "price": 152.00, "description": "First target reasoning" },
"tp2": { "price": 154.00, "description": "Second target reasoning" }
},
"riskToReward": "1:2",
"confirmationTrigger": "Technical signal to watch for",
"indicatorAnalysis": {
"rsi": "RSI level and interpretation",
"vwap": "VWAP relationship to price",
"obv": "Volume analysis if visible"
}
}
Return only the JSON object with your technical analysis.`
const response = await openai.chat.completions.create({
model: "gpt-4o-mini", // Cost-effective vision model
messages: [
{
role: "user",
content: [
{ type: "text", text: prompt },
{
type: "image_url",
image_url: {
url: `data:image/png;base64,${base64Image}`,
detail: "low" // Reduce token usage
}
}
]
}
],
max_tokens: 1024,
temperature: 0.1
})
const content = response.choices[0]?.message?.content
if (!content) return null
console.log('AI response content:', content)
// Extract JSON from response
const match = content.match(/\{[\s\S]*\}/)
if (!match) {
console.error('No JSON found in response. Full content:', content)
return null
}
const json = match[0]
console.log('Raw JSON from AI:', json)
let result
try {
result = JSON.parse(json)
console.log('Parsed result:', result)
} catch (parseError) {
console.error('Failed to parse JSON:', parseError)
console.error('Raw JSON that failed:', json)
return null
}
// Sanitize the result to ensure no nested objects cause React issues
const sanitizedResult = {
summary: typeof result.summary === 'string' ? result.summary : String(result.summary || ''),
marketSentiment: result.marketSentiment || 'NEUTRAL',
keyLevels: {
support: Array.isArray(result.keyLevels?.support) ? result.keyLevels.support : [],
resistance: Array.isArray(result.keyLevels?.resistance) ? result.keyLevels.resistance : []
},
recommendation: result.recommendation || 'HOLD',
confidence: typeof result.confidence === 'number' ? result.confidence : 0,
reasoning: typeof result.reasoning === 'string' ? result.reasoning : String(result.reasoning || 'Basic technical analysis'),
...(result.entry && { entry: result.entry }),
...(result.stopLoss && { stopLoss: result.stopLoss }),
...(result.takeProfits && { takeProfits: result.takeProfits }),
...(result.riskToReward && { riskToReward: String(result.riskToReward) }),
...(result.confirmationTrigger && { confirmationTrigger: String(result.confirmationTrigger) }),
...(result.indicatorAnalysis && { indicatorAnalysis: result.indicatorAnalysis })
}
// Optionally: validate result structure here
return sanitizedResult as AnalysisResult
} catch (e) {
console.error('AI analysis error:', e)
return null
}
}
async analyzeMultipleScreenshots(filenames: string[]): Promise<AnalysisResult | null> {
try {
const screenshotsDir = path.join(process.cwd(), 'screenshots')
// Read all image files and convert to base64
const images = await Promise.all(
filenames.map(async (filename) => {
const imagePath = path.join(screenshotsDir, filename)
const imageBuffer = await fs.readFile(imagePath)
const base64Image = imageBuffer.toString('base64')
return {
type: "image_url" as const,
image_url: {
url: `data:image/png;base64,${base64Image}`,
detail: "high" as const
}
}
})
)
const layoutInfo = filenames.map(f => {
if (f.includes('_ai_')) return 'AI Layout'
if (f.includes('_diy_') || f.includes('_Diy module_')) return 'DIY Module Layout'
return 'Unknown Layout'
}).join(' and ')
const prompt = `You are a professional technical chart analysis expert. I'm providing you with ${filenames.length} TradingView chart screenshots from different layouts: ${layoutInfo}.
**IMPORTANT**: Please analyze ALL screenshots together to provide comprehensive trading advice. Compare the different layouts and use ALL available information to make the most informed recommendation.
**Analysis Requirements:**
1. Examine ALL charts for:
- Current price action and trend direction across all timeframes/layouts
- Key support and resistance levels visible in any chart
- Technical indicator readings (RSI, moving averages, volume, etc.)
- Chart patterns or formations
- Market structure elements
- Any divergences or confirmations between the layouts
2. **Cross-Layout Analysis**:
- Compare insights from different chart layouts
- Look for confirmations or contradictions between views
- Identify which layout provides the clearest signals
- Use multiple perspectives to increase confidence
3. **Comprehensive Trading Setup**:
- Provide entry, stop loss, and take profit levels
- Include risk-to-reward analysis
- Suggest confirmation triggers
- Rate your confidence based on multi-layout consensus
**Response Format** (return only valid JSON):
{
"summary": "Comprehensive analysis of all charts including cross-layout insights and consensus",
"marketSentiment": "BULLISH|BEARISH|NEUTRAL",
"keyLevels": {
"support": [array of support levels from all charts],
"resistance": [array of resistance levels from all charts]
},
"recommendation": "BUY|SELL|HOLD",
"confidence": 85,
"reasoning": "Multi-layout technical analysis reasoning explaining how different charts confirm or contradict each other",
"entry": {
"price": 150.50,
"buffer": "±0.25",
"rationale": "Entry reasoning based on multiple chart analysis"
},
"stopLoss": {
"price": 148.00,
"rationale": "Stop loss reasoning considering all layouts"
},
"takeProfits": {
"tp1": { "price": 152.00, "description": "First target based on multi-chart analysis" },
"tp2": { "price": 154.00, "description": "Second target with cross-layout confirmation" }
},
"riskToReward": "1:2.5",
"confirmationTrigger": "Multi-layout signal confirmation to watch for",
"indicatorAnalysis": {
"rsi": "RSI analysis across layouts",
"vwap": "VWAP analysis from multiple views",
"obv": "Volume analysis synthesis",
"crossLayoutConsensus": "How well different layouts agree on the signals"
},
"layoutComparison": {
"aiLayout": "Insights specific to AI layout",
"diyLayout": "Insights specific to DIY module layout",
"consensus": "Areas where both layouts agree",
"divergences": "Areas where layouts show different signals"
}
}
Analyze all provided screenshots comprehensively and return only the JSON response.`
const messages = [
{
role: "user" as const,
content: [
{ type: "text" as const, text: prompt },
...images
]
}
]
console.log(`🤖 Sending ${filenames.length} screenshots to OpenAI for multi-layout analysis...`)
const response = await openai.chat.completions.create({
model: "gpt-4o-mini", // Cost-effective model with vision capabilities
messages,
max_tokens: 2000,
temperature: 0.1
})
const content = response.choices[0]?.message?.content
if (!content) {
throw new Error('No response from OpenAI')
}
console.log('🔍 Raw OpenAI response:', content.substring(0, 200) + '...')
// Parse JSON response
const jsonMatch = content.match(/\{[\s\S]*\}/)
if (!jsonMatch) {
throw new Error('No JSON found in response')
}
const analysis = JSON.parse(jsonMatch[0])
console.log('✅ Multi-layout analysis parsed successfully')
return analysis as AnalysisResult
} catch (error: any) {
console.error('❌ Multi-screenshot AI analysis failed:', error.message)
console.error('Full error:', error)
return null
}
}
async captureAndAnalyze(
symbol: string,
timeframe: string,
credentials: TradingViewCredentials
): Promise<AnalysisResult | null> {
try {
console.log(`Starting automated capture and analysis for ${symbol} ${timeframe}`)
// Capture screenshot using automation
const screenshot = await enhancedScreenshotService.captureQuick(symbol, timeframe, credentials)
if (!screenshot) {
throw new Error('Failed to capture screenshot')
}
console.log(`Screenshot captured: ${screenshot}`)
// Analyze the captured screenshot
const analysis = await this.analyzeScreenshot(screenshot)
if (!analysis) {
throw new Error('Failed to analyze screenshot')
}
console.log(`Analysis completed for ${symbol} ${timeframe}`)
return analysis
} catch (error) {
console.error('Automated capture and analysis failed:', error)
return null
}
}
async captureAndAnalyzeMultiple(
symbols: string[],
timeframes: string[],
credentials: TradingViewCredentials
): Promise<Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }>> {
const results: Array<{ symbol: string; timeframe: string; analysis: AnalysisResult | null }> = []
for (const symbol of symbols) {
for (const timeframe of timeframes) {
try {
console.log(`Processing ${symbol} ${timeframe}...`)
const analysis = await this.captureAndAnalyze(symbol, timeframe, credentials)
results.push({
symbol,
timeframe,
analysis
})
// Small delay between captures to avoid overwhelming the system
await new Promise(resolve => setTimeout(resolve, 2000))
} catch (error) {
console.error(`Failed to process ${symbol} ${timeframe}:`, error)
results.push({
symbol,
timeframe,
analysis: null
})
}
}
}
return results
}
async captureAndAnalyzeWithConfig(config: ScreenshotConfig): Promise<{
screenshots: string[]
analysis: AnalysisResult | null
}> {
try {
console.log(`Starting automated capture with config for ${config.symbol} ${config.timeframe}`)
// Capture screenshots using enhanced service
const screenshots = await enhancedScreenshotService.captureWithLogin(config)
if (screenshots.length === 0) {
throw new Error('No screenshots captured')
}
console.log(`${screenshots.length} screenshot(s) captured`)
let analysis: AnalysisResult | null = null
if (screenshots.length === 1) {
// Single screenshot analysis
analysis = await this.analyzeScreenshot(screenshots[0])
} else {
// Multiple screenshots analysis
analysis = await this.analyzeMultipleScreenshots(screenshots)
}
if (!analysis) {
throw new Error('Failed to analyze screenshots')
}
console.log(`Analysis completed for ${config.symbol} ${config.timeframe}`)
return {
screenshots,
analysis
}
} catch (error) {
console.error('Automated capture and analysis with config failed:', error)
return {
screenshots: [],
analysis: null
}
}
}
}
export const aiAnalysisService = new AIAnalysisService()