// Simple automation service for basic start/stop functionality class SimpleAutomation { constructor() { this.isRunning = false; this.config = null; this.intervalId = null; this.stats = { totalCycles: 0, totalTrades: 0, startTime: null, lastActivity: null, status: 'Stopped' }; } async start(config) { try { if (this.isRunning) { return { success: false, message: 'Automation already running' }; } // Validate basic config if (!config.selectedTimeframes || config.selectedTimeframes.length === 0) { return { success: false, message: 'At least one timeframe required' }; } this.config = config; this.isRunning = true; this.stats.startTime = new Date().toISOString(); this.stats.status = 'Running'; this.stats.totalCycles = 0; // Detect strategy const timeframes = config.selectedTimeframes; let strategy = 'General'; const isScalping = timeframes.includes('5') || timeframes.includes('15') || timeframes.includes('30'); const isDayTrading = timeframes.includes('60') || timeframes.includes('120'); const isSwingTrading = timeframes.includes('240') || timeframes.includes('D'); if (isScalping) strategy = 'Scalping'; else if (isDayTrading) strategy = 'Day Trading'; else if (isSwingTrading) strategy = 'Swing Trading'; console.log('SIMPLE AUTOMATION: Starting ' + strategy + ' strategy'); console.log('TIMEFRAMES: [' + timeframes.join(', ') + ']'); console.log('MODE: ' + (config.mode || 'SIMULATION')); // Start simple monitoring cycle (10 minutes for safety) this.intervalId = setInterval(() => { this.runCycle(); }, 10 * 60 * 1000); // 10 minutes // First cycle after 30 seconds setTimeout(() => { this.runCycle(); }, 30000); return { success: true, message: strategy + ' automation started successfully', strategy: strategy, timeframes: timeframes }; } catch (error) { console.error('Failed to start automation:', error); return { success: false, message: 'Failed to start automation: ' + error.message }; } } async stop() { try { this.isRunning = false; this.stats.status = 'Stopped'; if (this.intervalId) { clearInterval(this.intervalId); this.intervalId = null; } console.log('SIMPLE AUTOMATION: Stopped'); return { success: true, message: 'Automation stopped successfully' }; } catch (error) { console.error('Failed to stop automation:', error); return { success: false, message: 'Failed to stop automation: ' + error.message }; } } async runCycle() { try { this.stats.totalCycles++; this.stats.lastActivity = new Date().toISOString(); console.log('🔄 AUTOMATION CYCLE ' + this.stats.totalCycles + ': ' + (this.config?.symbol || 'SOLUSD')); console.log('⏰ TIME: ' + new Date().toLocaleTimeString()); console.log('📊 STRATEGY: ' + (this.config.selectedTimeframes?.join(', ') || 'N/A') + ' timeframes'); if (this.config) { // Perform actual analysis using enhanced screenshot API await this.performAnalysis(); } } catch (error) { console.error('Error in automation cycle:', error); } } async performAnalysis() { console.log(`📊 TRUE PARALLEL ANALYSIS: Starting simultaneous analysis for ${this.config.selectedTimeframes.length} timeframes...`); console.log(`🚀 This will capture ${this.config.selectedTimeframes.length * 2} screenshots in parallel (${this.config.selectedTimeframes.length} timeframes × 2 layouts)`); try { // Use batch analysis API for true parallelism - captures all timeframes simultaneously const response = await fetch('http://localhost:3000/api/batch-analysis', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ symbol: this.config.symbol, timeframes: this.config.selectedTimeframes, // All timeframes at once! layouts: ['ai', 'diy'], analyze: true }) }); if (!response.ok) { console.warn(`⚠️ BATCH API ERROR: ${response.status}, falling back to sequential...`); return this.performSequentialAnalysis(); } const result = await response.json(); if (result.success && result.analysis) { console.log(`✅ PARALLEL ANALYSIS COMPLETE: ${result.totalScreenshots} screenshots captured`); console.log(`📊 COMBINED Recommendation: ${result.analysis.recommendation}`); console.log(`🎯 COMBINED Confidence: ${result.analysis.confidence}%`); console.log(`⏰ Timeframes analyzed: ${result.timeframes.join(', ')}`); // Check if we should execute a trade based on combined analysis if (this.shouldExecuteTrade(result.analysis)) { console.log('💰 TRADE SIGNAL: Executing trade...'); await this.executeTrade(result.analysis); } else { console.log('📈 SIGNAL: Combined analysis complete, no trade executed'); } return; } else { console.warn('⚠️ BATCH ANALYSIS: No valid data, falling back to sequential...'); return this.performSequentialAnalysis(); } } catch (error) { console.error(`❌ PARALLEL ANALYSIS FAILED:`, error); console.log(`🔄 FALLBACK: Using sequential analysis...`); return this.performSequentialAnalysis(); } } // Fallback sequential analysis method async performSequentialAnalysis() { try { console.log('📸 SEQUENTIAL ANALYSIS: Starting...'); const allResults = []; // Analyze each timeframe separately for (const timeframe of this.config.selectedTimeframes) { console.log(`📊 ANALYZING: ${timeframe} timeframe...`); // Use the enhanced screenshot API for each timeframe const response = await fetch('http://localhost:3000/api/enhanced-screenshot', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ symbol: this.config.symbol, timeframe: timeframe, // Send one timeframe at a time layouts: ['ai', 'diy'], analyze: true }) }); if (!response.ok) { console.log(`⚠️ TIMEFRAME ${timeframe}: API error ${response.status}`); continue; } const result = await response.json(); if (result.analysis) { console.log(`✅ TIMEFRAME ${timeframe}: ${result.analysis.recommendation} (${result.analysis.confidence}%)`); allResults.push({ timeframe: timeframe, analysis: result.analysis, screenshots: result.screenshots }); } else { console.log(`⚠️ TIMEFRAME ${timeframe}: No analysis data`); } } if (allResults.length > 0) { console.log('✅ MULTI-TIMEFRAME ANALYSIS COMPLETE:'); // Combine results for overall decision const combinedAnalysis = this.combineTimeframeAnalysis(allResults); console.log('📊 COMBINED Recommendation: ' + combinedAnalysis.recommendation); console.log('🎯 COMBINED Confidence: ' + combinedAnalysis.confidence + '%'); console.log('⏰ Timeframes analyzed: ' + allResults.map(r => r.timeframe).join(', ')); // Check if we should execute a trade based on combined analysis if (this.shouldExecuteTrade(combinedAnalysis)) { console.log('💰 TRADE SIGNAL: Executing trade...'); await this.executeTrade(combinedAnalysis); } else { console.log('📈 SIGNAL: Combined analysis complete, no trade executed'); } } else { console.log('⚠️ ANALYSIS: No valid analysis data from any timeframe'); } } catch (error) { console.error('❌ ANALYSIS ERROR:', error.message); } } combineTimeframeAnalysis(results) { if (results.length === 1) { return results[0].analysis; } // Simple combination logic - can be enhanced const recommendations = results.map(r => r.analysis.recommendation?.toLowerCase() || 'hold'); const confidences = results.map(r => r.analysis.confidence || 0); // Count votes for each recommendation const votes = {}; recommendations.forEach(rec => { votes[rec] = (votes[rec] || 0) + 1; }); // Get majority recommendation const majorityRec = Object.keys(votes).reduce((a, b) => votes[a] > votes[b] ? a : b); // Average confidence, but boost if multiple timeframes agree const avgConfidence = confidences.reduce((sum, conf) => sum + conf, 0) / confidences.length; const agreementBonus = votes[majorityRec] > 1 ? 10 : 0; // +10% if multiple agree const finalConfidence = Math.min(95, avgConfidence + agreementBonus); console.log(`🔄 CONSENSUS: ${majorityRec.toUpperCase()} from ${votes[majorityRec]}/${results.length} timeframes`); return { recommendation: majorityRec, confidence: Math.round(finalConfidence), reasoning: `Multi-timeframe consensus from ${results.length} timeframes (${results.map(r => r.timeframe).join(', ')})`, timeframeResults: results }; } shouldExecuteTrade(analysis) { if (this.config.mode !== 'LIVE') { console.log('📊 SIMULATION MODE: Would execute trade'); return false; } const recommendation = analysis.recommendation?.toLowerCase() || ''; const confidence = analysis.confidence || 0; // Strategy-specific confidence requirements let minConfidence = 75; if (this.config.selectedTimeframes?.includes('5') || this.config.selectedTimeframes?.includes('15')) { minConfidence = 80; // Higher confidence for scalping } const isHighConfidence = confidence >= minConfidence; const isClearDirection = recommendation.includes('buy') || recommendation.includes('sell'); console.log('🎯 TRADE DECISION: ' + recommendation + ' (' + confidence + '%) - Min: ' + minConfidence + '%'); return isHighConfidence && isClearDirection; } async executeTrade(analysis) { try { console.log('💰 EXECUTING TRADE...'); // Map analysis recommendation to trading side const recommendation = analysis.recommendation?.toLowerCase() || ''; let side = ''; if (recommendation.includes('buy')) { side = 'BUY'; } else if (recommendation.includes('sell')) { side = 'SELL'; } else { console.log('❌ TRADE SKIP: Invalid recommendation - ' + recommendation); return { success: false, error: 'Invalid recommendation: ' + recommendation }; } // Use the trading API with proper fields const tradePayload = { symbol: this.config.symbol, side: side, amount: this.config.tradingAmount || 10, // Default to $10 if not set type: 'market', tradingMode: 'SPOT', analysis: analysis // Include analysis for reference }; console.log('📊 TRADE PAYLOAD:', tradePayload); const response = await fetch('http://localhost:3000/api/trading', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(tradePayload) }); const result = await response.json(); if (result.success) { console.log('✅ TRADE EXECUTED: ' + result.message); this.stats.totalTrades = (this.stats.totalTrades || 0) + 1; this.stats.successfulTrades = (this.stats.successfulTrades || 0) + 1; } else { console.log('❌ TRADE FAILED: ' + result.error); } return result; } catch (error) { console.error('❌ TRADE ERROR:', error.message); return { success: false, error: error.message }; } } getStatus() { return { isActive: this.isRunning, mode: this.config?.mode || 'SIMULATION', symbol: this.config?.symbol || 'SOLUSD', timeframes: this.config?.selectedTimeframes || [], automationType: 'SIMPLE', ...this.stats }; } } // Export singleton instance const simpleAutomation = new SimpleAutomation(); export { simpleAutomation };