import OpenAI from 'openai' import fs from 'fs/promises' import path from 'path' import { enhancedScreenshotService, ScreenshotConfig } from './enhanced-screenshot' import { TradingViewCredentials } from './tradingview-automation' import { progressTracker } from './progress-tracker' 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 // Professional execution zone zone?: { low: number high: number optimal: number } slippageBuffer?: number executionInstructions?: string } stopLoss?: { price: number rationale: string } takeProfits?: { tp1?: { price: number description: string rsiExpectation?: string obvExpectation?: string } tp2?: { price: number description: string rsiExpectation?: string obvExpectation?: string } } riskToReward?: string confirmationTrigger?: string // Professional Trading Desk Features leverageGuidance?: { timeframe: string suggestedLeverage: string positionSizePercent: string reasoning: string riskLevel: 'CONSERVATIVE' | 'MODERATE' | 'AGGRESSIVE' } indicatorRoadmap?: { rsi?: { atEntry: string atTP1: string atTP2?: string invalidation: string warningSignals: string } obv?: { atEntry: string atTP1: string atTP2?: string invalidation: string warningSignals: string } vwap?: { atEntry: string invalidation: string confirmationSignal: string } macd?: { atEntry: string expectedBehavior: string invalidation: string } } journalTemplate?: { preFilledData: { asset: string entry: number stopLoss: number tp1: number tp2?: number riskReward: string setupType: string } executionTracking: { confirmationReceived: string slippageExpected: string emotionalState: string executionNotes: string } postTradeAnalysis: { didFollowPlan: string lessonsLearned: string nextTimeImprovement: string } } scenarioManagement?: { invalidation: { priceLevel: number reasoning: string immediateAction: string nextOpportunity?: string } alternatives: { tighterStopOption?: string scaledEntryOption?: string counterTrendSetup?: string betterRiskReward?: string } livePositionGuidance?: { currentSituation?: string immediateRisk?: string optimalAction?: string emergencyExit?: string } } psychologyCoaching?: { mindsetReminder: string emotionalCheck: string disciplineNote: string riskManagementReminder: string } // AI-optimized risk management optimalRiskManagement?: { stopLossPercent: number // AI-recommended stop loss percentage takeProfitPercent: number // AI-recommended take profit percentage riskRewardRatio: number // Expected risk/reward ratio reasoning: string // Why these percentages are optimal marketVolatility: 'LOW' | 'MEDIUM' | 'HIGH' // Current volatility assessment timeHorizon: 'SCALP' | 'INTRADAY' | 'SWING' // Expected trade duration } indicatorAnalysis?: { rsi?: string vwap?: string obv?: string macd?: string crossLayoutConsensus?: string } layoutComparison?: { aiLayout?: string diyLayout?: string consensus?: string divergences?: string } timeframeRisk?: { assessment?: string positionSize?: string leverageRecommendation?: string } alternatives?: { tigherStopOption?: string scaledEntry?: string invalidationScenario?: string } } export class AIAnalysisService { private lastApiCall: number = 0 async analyzeScreenshot(filenameOrPath: string): Promise { try { let imagePath: string // Check if it's already a full path or just a filename if (path.isAbsolute(filenameOrPath)) { // It's already a full path imagePath = filenameOrPath } else { // It's just a filename, construct the full path const screenshotsDir = path.join(process.cwd(), 'screenshots') imagePath = path.join(screenshotsDir, filenameOrPath) } // Read image file const imageBuffer = await fs.readFile(imagePath) const base64Image = imageBuffer.toString('base64') const prompt = `You are now a professional trading assistant. You behave with the precision and decisiveness of a top proprietary desk trader. No vagueness, no fluff. **WHEN GIVING A TRADE SETUP:** Be 100% SPECIFIC. Provide: 1. **TIMEFRAME RISK ASSESSMENT**: - Lower timeframes = higher risk, higher leverage (5min scalp: 10x+ leverage, tight stops) - Higher timeframes = lower risk, lower leverage (4H: 2-3x leverage, wider stops) - Position sizing: Less money on lower timeframes, more on higher timeframes **TECHNICAL ANALYSIS FUNDAMENTALS:** **RSI (Relative Strength Index):** - Measures momentum on 0-100 scale - OVERBOUGHT: Above 70 (potential sell signal) - OVERSOLD: Below 30 (potential buy signal) - NEUTRAL: 30-70 range - ⚠️ CRITICAL: Read visual line position, not numerical value when they conflict **MACD (Moving Average Convergence Divergence):** - BULLISH CROSSOVER: MACD line crosses ABOVE signal line - BEARISH CROSSOVER: MACD line crosses BELOW signal line - HISTOGRAM: Green bars = bullish momentum, Red bars = bearish momentum - ZERO LINE: Above = bullish trend, Below = bearish trend **EMAs (Exponential Moving Averages):** - EMA 9 (Yellow): Short-term trend - EMA 20 (Orange): Medium-term trend - EMA 50 (Blue): Intermediate trend - EMA 200 (Red): Long-term trend - BULLISH STACK: 9 > 20 > 50 > 200 - BEARISH STACK: 9 < 20 < 50 < 200 **Stochastic RSI:** - OVERBOUGHT: Above 80 - OVERSOLD: Below 20 - BULLISH SIGNAL: %K crosses above %D in oversold territory - BEARISH SIGNAL: %K crosses below %D in overbought territory **VWAP (Volume Weighted Average Price):** - Above VWAP = Bullish sentiment - Below VWAP = Bearish sentiment - RECLAIM: Price moves back above VWAP (bullish) - REJECTION: Price fails at VWAP (bearish) **OBV (On-Balance Volume):** - Rising OBV = Volume supporting upward price movement - Falling OBV = Volume supporting downward price movement - DIVERGENCE: OBV direction differs from price (warning signal) **LAYOUT IDENTIFICATION:** **AI Layout (RSI + MACD + EMAs):** - TOP: RSI indicator (14-period momentum oscillator) - MIDDLE: EMAs (9,20,50,200) + ATR Bands + SVP - BOTTOM: MACD indicator with histogram - Focus: Momentum + Trend Analysis **DIY Layout (Stochastic RSI + VWAP + OBV):** - TOP: Stochastic RSI (more sensitive momentum) - MIDDLE: VWAP + Smart Money Concepts - BOTTOM: OBV (volume flow analysis) - Focus: Volume + Institutional Flow Analysis **PROFESSIONAL TRADING REQUIREMENTS:** 2. **ENTRY** - Exact price level with execution zone (high/low/optimal) - Slippage buffer (±0.25, ±0.50, etc.) - Rationale: e.g., "Rejection from 15 EMA + VWAP confluence near intraday supply" - Execution instructions: What to wait for before entering 3. **STOP-LOSS (SL)** - Exact level (not arbitrary) - Explain *why* it's there: "Above VWAP + failed breakout zone" 4. **TAKE PROFITS** - TP1: Immediate structure (ex: previous low at $149.20) - TP2: Extended target if momentum continues (e.g., $148.00) - Mention **expected RSI/OBV behavior** at each TP zone 5. **RISK-TO-REWARD** - Show R:R. Ex: "1:2.5 — Risking $X to potentially gain $Y" 6. **CONFIRMATION TRIGGER** - Exact signal to wait for: e.g., "Bearish engulfing candle on rejection from VWAP zone" - OBV: "Must be making lower highs + dropping below 30min average" - RSI: "Should remain under 50 on rejection. Overbought ≥70 = wait" 7. **INDICATOR ROADMAP** - tell me: - **RSI**: If RSI crosses above 70 while price is under resistance → *wait* - **VWAP**: If price retakes VWAP with bullish momentum → *consider invalidation* - **OBV**: If OBV starts climbing while price stays flat → *early exit or reconsider bias* - **MACD**: Expected behavior at entry and targets 8. **ALTERNATIVES** - If SL is far, offer tighter SL alternative or scaled entry near next level - Suggest re-entry if original setup invalidates but price reaches better location - Counter-trend opportunities if main setup fails 9. **LEVERAGE & POSITION SIZING** - Based on timeframe: 5m = 10x+, 1H = 3-5x, 4H+ = 1-3x - Position size percentage recommendation - Risk level assessment (CONSERVATIVE/MODERATE/AGGRESSIVE) 10. **PSYCHOLOGY COACHING** - Give firm reminders when emotions cloud judgment - Reframe mindset if revenge trading, fearful, or hesitant to execute - Discipline notes and risk management reminders 11. **JOURNAL TEMPLATE** - Pre-filled trade data ready for journaling - Execution tracking fields - Post-trade analysis framework **TIMEFRAME RISK ASSESSMENT:** - **1m-15m**: High risk, 10x+ leverage, tight stops, scalping setups - **1H-4H**: Medium risk, 3-5x leverage, moderate stops, swing setups - **1D+**: Low risk, 1-2x leverage, wide stops, position setups **ANALYSIS REQUIREMENTS:** 1. **IDENTIFY LAYOUT TYPE**: AI Layout (RSI/MACD/EMAs) or DIY Layout (Stoch RSI/VWAP/OBV) 2. **MOMENTUM ASSESSMENT**: - Check primary momentum indicator (RSI or Stochastic RSI) - Look for overbought/oversold conditions - Identify momentum divergences 3. **TREND CONFIRMATION**: - EMA alignment and price position (AI Layout) - VWAP position and smart money zones (DIY Layout) - Determine trend direction and strength 4. **VOLUME ANALYSIS**: - MACD histogram momentum (AI Layout) - OBV volume flow confirmation (DIY Layout) - Volume should confirm price movements 5. **PRECISE TRADING LEVELS**: - **ENTRY**: Exact execution zone with buffer and technical rationale - **STOP LOSS**: Exact level with clear reasoning - **TAKE PROFITS**: TP1 (structure) and TP2 (extension) with indicator expectations - **RISK/REWARD**: Calculate R:R ratio 6. **CONFIRMATION TRIGGERS**: Specific signals to wait for before entry NEVER be vague — always define the level, the behavior, and the action. Provide your analysis in this exact JSON format: { "layoutDetected": "AI Layout|DIY Layout", "summary": "Professional trading desk analysis with precise execution instructions", "marketSentiment": "BULLISH|BEARISH|NEUTRAL", "keyLevels": { "support": [visible support price levels as numbers], "resistance": [visible resistance price levels as numbers] }, "recommendation": "BUY|SELL|HOLD", "confidence": 85, "reasoning": "Technical analysis reasoning based on established TA principles and indicator confluence", "entry": { "price": 150.50, "zone": { "low": 150.20, "high": 150.80, "optimal": 150.50 }, "slippageBuffer": 0.25, "rationale": "Specific technical reasoning based on indicator confluence", "executionInstructions": "Wait for bearish engulfing candle on rejection from VWAP zone" }, "stopLoss": { "price": 148.00, "rationale": "Above VWAP + failed breakout zone - hard invalidation level" }, "takeProfits": { "tp1": { "price": 152.00, "description": "Previous low structure - immediate target", "rsiExpectation": "RSI should dip near 30 oversold but hold without strong divergence", "obvExpectation": "OBV should continue lower lows confirming distribution" }, "tp2": { "price": 154.00, "description": "Extended flush target at prior liquidity sweep", "rsiExpectation": "RSI may show bullish divergence warning of bounce", "obvExpectation": "OBV flattening could signal exhaustion" } }, "riskToReward": "1:2.5 — Risking $2.50 to potentially gain $6.25", "confirmationTrigger": "Bearish engulfing candle on rejection from $150.50-150.80 zone", "leverageGuidance": { "timeframe": "30m", "suggestedLeverage": "5x-8x", "positionSizePercent": "1-2%", "reasoning": "Medium timeframe allows moderate leverage with controlled risk", "riskLevel": "MODERATE" }, "indicatorRoadmap": { "rsi": { "atEntry": "Should remain under 50 on rejection", "atTP1": "Expected to dip near 30 without strong divergence", "atTP2": "May show bullish divergence warning of bounce", "invalidation": "If crosses above 70 while price under resistance - wait", "warningSignals": "Divergence with price action suggests momentum shift" }, "obv": { "atEntry": "Must be making lower highs + dropping below 30min average", "atTP1": "Should continue lower lows confirming distribution", "atTP2": "Flattening could signal selling exhaustion", "invalidation": "If starts climbing while price stays flat - early exit", "warningSignals": "Volume divergence suggests institutional accumulation" }, "vwap": { "atEntry": "Price should reject from VWAP resistance", "invalidation": "If price retakes VWAP with bullish momentum", "confirmationSignal": "Rejection wick from VWAP zone" }, "macd": { "atEntry": "Should show bearish crossover or histogram declining", "expectedBehavior": "Continued bearish momentum through targets", "invalidation": "Bullish crossover above signal line" } }, "journalTemplate": { "preFilledData": { "asset": "SOLUSD", "entry": 150.50, "stopLoss": 148.00, "tp1": 152.00, "tp2": 154.00, "riskReward": "1:2.5", "setupType": "VWAP rejection + momentum continuation" }, "executionTracking": { "confirmationReceived": "Did you wait for bearish engulfing candle?", "slippageExpected": "±0.25 acceptable", "emotionalState": "Calm / FOMO / Hesitant / Revenge-trading?", "executionNotes": "Entry timing and fill quality" }, "postTradeAnalysis": { "didFollowPlan": "Followed entry rules and exit strategy?", "lessonsLearned": "Key takeaways from this trade", "nextTimeImprovement": "What to do better next trade" } }, "scenarioManagement": { "invalidation": { "priceLevel": 148.00, "reasoning": "Above VWAP + failed breakdown - trend shifting bullish", "immediateAction": "Cut position immediately, reassess bias", "nextOpportunity": "Wait for retest of breakdown level for new short" }, "alternatives": { "tighterStopOption": "Use $149.20 stop if want tighter risk (1:1.5 R:R)", "scaledEntryOption": "Scale in 50% at $150.50, 50% at $150.80 rejection", "counterTrendSetup": "Long scalp at $147.80-148.20 if liquidity sweep with RSI divergence", "betterRiskReward": "Wait for deeper retracement to $149.00 for 1:3 R:R" } }, "psychologyCoaching": { "mindsetReminder": "Missing a move is better than revenge-trading a bad entry", "emotionalCheck": "Are you trading from FOMO or following your plan?", "disciplineNote": "Stick to your $150.50-150.80 rejection zone - discipline > FOMO", "riskManagementReminder": "This is scalp/swing hybrid - take profits aggressively, don't dream of trend reversal" } } Return only the JSON object with your professional trading 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) }), // Professional Trading Desk Features ...(result.leverageGuidance && { leverageGuidance: result.leverageGuidance }), ...(result.indicatorRoadmap && { indicatorRoadmap: result.indicatorRoadmap }), ...(result.journalTemplate && { journalTemplate: result.journalTemplate }), ...(result.scenarioManagement && { scenarioManagement: result.scenarioManagement }), ...(result.psychologyCoaching && { psychologyCoaching: result.psychologyCoaching }), // Legacy fields for backward compatibility ...(result.indicatorAnalysis && { indicatorAnalysis: result.indicatorAnalysis }), ...(result.optimalRiskManagement && { optimalRiskManagement: result.optimalRiskManagement }), ...(result.timeframeRisk && { timeframeRisk: result.timeframeRisk }), ...(result.alternatives && { alternatives: result.alternatives }) } // Optionally: validate result structure here return sanitizedResult as AnalysisResult } catch (e) { console.error('AI analysis error:', e) return null } } async analyzeMultipleScreenshots(filenamesOrPaths: string[]): Promise { try { // Read all image files and convert to base64 const images = await Promise.all( filenamesOrPaths.map(async (filenameOrPath) => { let imagePath: string // Check if it's already a full path or just a filename if (path.isAbsolute(filenameOrPath)) { // It's already a full path imagePath = filenameOrPath } else { // It's just a filename, construct the full path const screenshotsDir = path.join(process.cwd(), 'screenshots') imagePath = path.join(screenshotsDir, filenameOrPath) } 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 = filenamesOrPaths.map(f => { const filename = path.basename(f) // Extract filename from path if (filename.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 now a professional trading assistant. You behave with the precision and decisiveness of a top proprietary desk trader. No vagueness, no fluff. I'm providing you with ${filenamesOrPaths.length} TradingView chart screenshots from different layouts: ${layoutInfo}. **WHEN GIVING A TRADE SETUP:** Be 100% SPECIFIC with MULTI-LAYOUT CONSENSUS: 1. **CROSS-LAYOUT VALIDATION**: - Compare momentum signals between layouts (RSI vs Stochastic RSI) - Confirm trend direction with both EMA stack and VWAP positioning - Volume confirmation: MACD histogram vs OBV flow agreement - ONLY trade when layouts show consensus - avoid conflicting signals 2. **TIMEFRAME RISK ASSESSMENT**: - Lower timeframes = higher risk, higher leverage (5min scalp: 10x+ leverage, tight stops) - Higher timeframes = lower risk, lower leverage (4H: 2-3x leverage, wider stops) - Position sizing: Less money on lower timeframes, more on higher timeframes **TECHNICAL ANALYSIS FUNDAMENTALS:** **RSI (Relative Strength Index):** - OVERBOUGHT: Above 70 (potential sell signal) - OVERSOLD: Below 30 (potential buy signal) - NEUTRAL: 30-70 range - ⚠️ CRITICAL: Read visual line position, not numerical value when they conflict **MACD (Moving Average Convergence Divergence):** - BULLISH CROSSOVER: MACD line crosses ABOVE signal line - BEARISH CROSSOVER: MACD line crosses BELOW signal line - HISTOGRAM: Green bars = bullish momentum, Red bars = bearish momentum - ZERO LINE: Above = bullish trend, Below = bearish trend **EMAs (Exponential Moving Averages):** - EMA 9 (Yellow): Short-term trend - EMA 20 (Orange): Medium-term trend - EMA 50 (Blue): Intermediate trend - EMA 200 (Red): Long-term trend - BULLISH STACK: 9 > 20 > 50 > 200 - BEARISH STACK: 9 < 20 < 50 < 200 **Stochastic RSI:** - OVERBOUGHT: Above 80 - OVERSOLD: Below 20 - BULLISH SIGNAL: %K crosses above %D in oversold territory - BEARISH SIGNAL: %K crosses below %D in overbought territory **VWAP (Volume Weighted Average Price):** - Above VWAP = Bullish sentiment - Below VWAP = Bearish sentiment - RECLAIM: Price moves back above VWAP (bullish) - REJECTION: Price fails at VWAP (bearish) **OBV (On-Balance Volume):** - Rising OBV = Volume supporting upward price movement - Falling OBV = Volume supporting downward price movement - DIVERGENCE: OBV direction differs from price (warning signal) **MULTI-LAYOUT ANALYSIS:** **AI Layout (RSI + MACD + EMAs):** - Focus: Momentum + Trend Analysis - Primary indicators: RSI, MACD, EMAs - Use for: Trend direction, momentum signals, entry/exit timing **DIY Layout (Stochastic RSI + VWAP + OBV):** - Focus: Volume + Institutional Flow Analysis - Primary indicators: Stochastic RSI, VWAP, OBV - Use for: Volume confirmation, institutional sentiment, fair value **PROFESSIONAL MULTI-LAYOUT REQUIREMENTS:** 3. **ENTRY WITH CROSS-LAYOUT CONFIRMATION** - Exact price level with execution zone (high/low/optimal) - Slippage buffer (±0.25, ±0.50, etc.) - Rationale: e.g., "AI Layout: RSI oversold + MACD bullish crossover | DIY Layout: Stochastic RSI oversold crossover + VWAP reclaim" - Execution instructions: What to wait for before entering 4. **STOP-LOSS (SL)** - Exact level based on BOTH layouts - Explain *why*: "Below VWAP AND under EMA 20 support confluence" 5. **TAKE PROFITS WITH INDICATOR EXPECTATIONS** - TP1: Immediate structure with BOTH layout expectations - TP2: Extended target with cross-layout momentum analysis - Expected behavior for ALL indicators (RSI, Stochastic RSI, MACD, OBV, VWAP, EMAs) 6. **RISK-TO-REWARD** - Show R:R with cross-layout validation 7. **CONFIRMATION TRIGGER** - Exact signal from BOTH layouts: e.g., "AI Layout: MACD bullish crossover AND DIY Layout: VWAP reclaim with OBV rising" 8. **CROSS-LAYOUT CONSENSUS ANALYSIS** - Where layouts AGREE (strengthen confidence) - Where layouts DIVERGE (caution signals) - Overall consensus assessment 9. **MULTI-LAYOUT INDICATOR ROADMAP** - Expected behavior for ALL indicators at entry and targets - Cross-validation warning signals - Invalidation triggers from either layout 10. **LEVERAGE & POSITION SIZING** - Based on timeframe AND cross-layout confidence - Higher confidence from consensus = slightly higher position size - Conflicting signals = reduce size or wait **TIMEFRAME RISK ASSESSMENT:** - **1m-15m**: High risk, 10x+ leverage, tight stops, scalping setups - **1H-4H**: Medium risk, 3-5x leverage, moderate stops, swing setups - **1D+**: Low risk, 1-2x leverage, wide stops, position setups **ANALYSIS PROCESS:** 1. **Identify Layout Types**: Determine which layouts are provided 2. **Cross-Layout Momentum Assessment**: Compare RSI vs Stochastic RSI signals 3. **Cross-Layout Trend Confirmation**: EMA alignment vs VWAP positioning 4. **Cross-Layout Volume Analysis**: MACD histogram vs OBV flow agreement 5. **Consensus vs Divergence**: Where layouts agree/disagree 6. **Risk Assessment**: Adjust for timeframe and layout confidence NEVER be vague — always define the level, the behavior, and the cross-layout consensus. **Response Format** (return only valid JSON): { "summary": "Professional multi-layout analysis with cross-layout consensus and precise execution instructions", "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 with cross-layout confirmation", "layoutsAnalyzed": ["AI Layout", "DIY Layout"], "layoutComparison": { "aiLayout": "AI Layout analysis with RSI, MACD, EMA insights", "diyLayout": "DIY Layout analysis with Stochastic RSI, VWAP, OBV insights", "consensus": "Where both layouts agree - strengthens setup confidence", "divergences": "Where layouts conflict - caution signals or wait" }, "entry": { "price": 150.50, "zone": { "low": 150.20, "high": 150.80, "optimal": 150.50 }, "slippageBuffer": 0.25, "rationale": "Cross-layout confluence: AI Layout RSI oversold + MACD bullish crossover | DIY Layout Stochastic RSI oversold + VWAP reclaim", "executionInstructions": "Wait for both MACD bullish crossover AND VWAP reclaim with rising OBV" }, "stopLoss": { "price": 148.00, "rationale": "Below VWAP AND under EMA 20 support confluence - invalidates both layouts" }, "takeProfits": { "tp1": { "price": 152.00, "description": "Previous resistance - cross-layout profit taking zone", "rsiExpectation": "RSI should reach 60-65 range", "obvExpectation": "OBV should show higher highs confirming momentum", "stochRsiExpectation": "Stochastic RSI should reach 70-80 range", "vwapExpectation": "Price should maintain above VWAP" }, "tp2": { "price": 154.00, "description": "Extended target - momentum continuation zone", "rsiExpectation": "RSI may reach overbought 70+ (momentum exhaustion warning)", "obvExpectation": "OBV continues rising but watch for divergence", "stochRsiExpectation": "Stochastic RSI likely overbought 80+ (take profits)", "vwapExpectation": "Price extension above VWAP - institutional profit taking" } }, "riskToReward": "1:2.5 — Risking $2.50 to potentially gain $6.25", "confirmationTrigger": "AI Layout: MACD bullish crossover AND DIY Layout: VWAP reclaim with rising OBV", "leverageGuidance": { "timeframe": "1H", "suggestedLeverage": "3-5x", "positionSizePercent": "2-3%", "reasoning": "Medium timeframe with strong cross-layout consensus allows moderate leverage", "riskLevel": "MODERATE" }, "indicatorRoadmap": { "rsi": { "atEntry": "Should be oversold below 30 with upward momentum", "atTP1": "Expected to reach 60-65 range", "atTP2": "May reach overbought 70+ (momentum exhaustion warning)", "invalidation": "If fails to bounce from oversold levels", "warningSignals": "Bearish divergence at TP2 levels" }, "stochRsi": { "atEntry": "Should show %K crossing above %D in oversold territory", "atTP1": "Expected to reach 70-80 range", "atTP2": "Likely overbought 80+ (take profits)", "invalidation": "If %K crosses below %D without follow through", "warningSignals": "Bearish crossover in overbought territory" }, "obv": { "atEntry": "Must be rising confirming buying pressure", "atTP1": "Should show higher highs confirming momentum", "atTP2": "Continues rising but watch for divergence", "invalidation": "If starts declining while price rises", "warningSignals": "Bearish divergence suggests institutional selling" }, "vwap": { "atEntry": "Price should reclaim VWAP with strong volume", "invalidation": "If price rejected back below VWAP", "confirmationSignal": "Strong hold above VWAP after reclaim" }, "macd": { "atEntry": "Should show bullish crossover above signal line", "expectedBehavior": "Histogram turning green, momentum building", "invalidation": "Bearish crossover or histogram declining" } }, "journalTemplate": { "preFilledData": { "asset": "SOLUSD", "entry": 150.50, "stopLoss": 148.00, "tp1": 152.00, "tp2": 154.00, "riskReward": "1:2.5", "setupType": "Multi-layout consensus: RSI oversold + VWAP reclaim" }, "executionTracking": { "confirmationReceived": "Did you wait for BOTH MACD crossover AND VWAP reclaim?", "slippageExpected": "±0.25 acceptable", "emotionalState": "Calm / FOMO / Hesitant / Revenge-trading?", "executionNotes": "Cross-layout signal timing and fill quality" }, "postTradeAnalysis": { "didFollowPlan": "Followed multi-layout entry rules and exit strategy?", "lessonsLearned": "Key takeaways from cross-layout analysis", "nextTimeImprovement": "Better cross-layout signal timing" } }, "scenarioManagement": { "invalidation": { "priceLevel": 148.00, "reasoning": "Below VWAP AND under EMA 20 - both layouts invalidated", "immediateAction": "Cut position immediately, both setups failed", "nextOpportunity": "Wait for new multi-layout consensus setup" }, "alternatives": { "tighterStopOption": "Use $149.20 stop if want tighter risk (1:1.8 R:R)", "scaledEntryOption": "Scale in 50% at VWAP reclaim, 50% at MACD crossover", "counterTrendSetup": "Short if both layouts show overbought rejection at resistance", "betterRiskReward": "Wait for deeper pullback to $149.00 for 1:3.5 R:R" } }, "psychologyCoaching": { "mindsetReminder": "Cross-layout consensus = higher probability, but still requires discipline", "emotionalCheck": "Are you trading the consensus or forcing conflicting signals?", "disciplineNote": "Wait for BOTH layouts to confirm - patience pays in multi-layout analysis", "riskManagementReminder": "Even with consensus, risk management is paramount" } } Return only the JSON object with your professional multi-layout trading analysis.` const messages = [ { role: "user" as const, content: [ { type: "text" as const, text: prompt }, ...images ] } ] console.log(`🤖 Sending ${filenamesOrPaths.length} screenshots to OpenAI for multi-layout analysis...`) // Add rate limiting check to prevent 429 errors const now = Date.now() if (this.lastApiCall && (now - this.lastApiCall) < 2000) { const waitTime = 2000 - (now - this.lastApiCall) console.log(`⏳ Rate limiting: waiting ${waitTime}ms before OpenAI call`) await new Promise(resolve => setTimeout(resolve, waitTime)) } try { const response = await openai.chat.completions.create({ model: "gpt-4o-mini", // Cost-effective model with vision capabilities messages, max_tokens: 2000, temperature: 0.1 }) this.lastApiCall = Date.now() 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) { if (error.status === 429) { console.log('⏳ OpenAI rate limit hit - will retry on next cycle') // Don't throw the error, just return null to skip this cycle gracefully return null } throw error } } 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 { 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> { 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 }> { const { sessionId } = config try { console.log(`Starting automated capture with config for ${config.symbol} ${config.timeframe}`) // Capture screenshots using enhanced service (this will handle its own progress) const screenshots = await enhancedScreenshotService.captureWithLogin(config) if (screenshots.length === 0) { throw new Error('No screenshots captured') } console.log(`${screenshots.length} screenshot(s) captured`) // Add AI analysis step to progress if sessionId exists if (sessionId) { progressTracker.updateStep(sessionId, 'analysis', 'active', 'Running AI analysis on screenshots...') } 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) { if (sessionId) { progressTracker.updateStep(sessionId, 'analysis', 'error', 'AI analysis failed to generate results') } throw new Error('Failed to analyze screenshots') } console.log(`Analysis completed for ${config.symbol} ${config.timeframe}`) if (sessionId) { progressTracker.updateStep(sessionId, 'analysis', 'completed', 'AI analysis completed successfully!') // Mark session as complete setTimeout(() => progressTracker.deleteSession(sessionId), 1000) } // Trigger post-analysis cleanup in development mode if (process.env.NODE_ENV === 'development') { try { // Dynamic import to avoid circular dependencies const aggressiveCleanupModule = await import('./aggressive-cleanup') const aggressiveCleanup = aggressiveCleanupModule.default // Run cleanup in background, don't block the response aggressiveCleanup.runPostAnalysisCleanup().catch(console.error) } catch (cleanupError) { console.error('Error triggering post-analysis cleanup:', cleanupError) } } return { screenshots, analysis } } catch (error) { console.error('Automated capture and analysis with config failed:', error) if (sessionId) { // Find the active step and mark it as error const progress = progressTracker.getProgress(sessionId) if (progress) { const activeStep = progress.steps.find(step => step.status === 'active') if (activeStep) { progressTracker.updateStep(sessionId, activeStep.id, 'error', error instanceof Error ? error.message : 'Unknown error') } } // Clean up session setTimeout(() => progressTracker.deleteSession(sessionId), 5000) } return { screenshots: [], analysis: null } } } } export const aiAnalysisService = new AIAnalysisService()