import { enhancedScreenshotService } from './enhanced-screenshot-robust' import { aiAnalysisService } from './ai-analysis' import { automatedCleanupService } from './automated-cleanup-service' import aggressiveCleanup from './aggressive-cleanup' export interface TradingConfig { symbol: string timeframes: string[] layouts: string[] intervalMs: number // How often to run analysis maxCycles?: number // Optional limit for testing } export class AutoTradingService { private isRunning = false private currentCycle = 0 private config: TradingConfig | null = null async start(config: TradingConfig) { if (this.isRunning) { console.log('āš ļø Trading service already running') return } this.isRunning = true this.config = config this.currentCycle = 0 console.log('šŸš€ Starting automated trading service with robust cleanup...') console.log('šŸ”§ Config:', config) // Start background cleanup service automatedCleanupService.start(30000) // Every 30 seconds // Start aggressive cleanup system aggressiveCleanup.startPeriodicCleanup() try { while (this.isRunning && (!config.maxCycles || this.currentCycle < config.maxCycles)) { this.currentCycle++ console.log(`\nšŸ”„ === TRADING CYCLE ${this.currentCycle} ===`) await this.runTradingCycle(config) if (this.isRunning) { console.log(`ā³ Waiting ${config.intervalMs/1000} seconds until next cycle...`) await new Promise(resolve => setTimeout(resolve, config.intervalMs)) } } if (config.maxCycles && this.currentCycle >= config.maxCycles) { console.log(`āœ… Completed ${this.currentCycle} cycles (reached max limit)`) } } catch (error) { console.error('āŒ Trading service error:', error) } finally { await this.stop() } } async stop() { console.log('šŸ›‘ Stopping automated trading service...') this.isRunning = false // Stop cleanup services automatedCleanupService.stop() aggressiveCleanup.stop() // Force cleanup all browser sessions try { await enhancedScreenshotService.cleanup() await aggressiveCleanup.forceCleanup() console.log('āœ… Trading service stopped and cleaned up') } catch (cleanupError) { console.error('āŒ Error during final cleanup:', cleanupError) } } private async runTradingCycle(config: TradingConfig): Promise { console.log(`šŸ”„ Running trading cycle ${this.currentCycle}...`) // Process each timeframe sequentially to avoid resource conflicts for (const timeframe of config.timeframes) { if (!this.isRunning) break // Check if service was stopped try { console.log(`\nšŸ“Š Processing ${config.symbol} ${timeframe}...`) // Capture screenshots with robust cleanup const screenshots = await enhancedScreenshotService.captureWithLogin({ symbol: config.symbol, timeframe: timeframe, layouts: config.layouts, analyze: false // We'll analyze separately }) if (screenshots.length > 0) { console.log(`āœ… Captured ${screenshots.length} screenshots for ${timeframe}`) // Analyze screenshots try { let analysis = null if (screenshots.length === 1) { analysis = await aiAnalysisService.analyzeScreenshot(screenshots[0]) } else if (screenshots.length > 1) { analysis = await aiAnalysisService.analyzeMultipleScreenshots(screenshots) } if (analysis) { console.log(`āœ… Analysis completed for ${timeframe}`) console.log(`šŸ“ˆ Sentiment: ${analysis.marketSentiment || 'Unknown'}`) console.log(`šŸŽÆ Recommendation: ${analysis.recommendation}, Confidence: ${analysis.confidence}%`) // Here you would implement your trading logic based on analysis await this.processAnalysisForTrading(analysis, config.symbol, timeframe) } else { console.warn(`āš ļø No analysis returned for ${timeframe}`) } } catch (analysisError) { console.error(`āŒ Analysis failed for ${timeframe}:`, analysisError) } } else { console.error(`āŒ No screenshots captured for ${timeframe}`) } // Small delay between timeframes to prevent overwhelming the system if (config.timeframes.indexOf(timeframe) < config.timeframes.length - 1) { console.log('ā³ Brief pause before next timeframe...') await new Promise(resolve => setTimeout(resolve, 5000)) } } catch (error) { console.error(`āŒ Error processing ${timeframe}:`, error) // Continue with next timeframe even if one fails } } console.log(`āœ… Trading cycle ${this.currentCycle} completed`) // Run post-cycle cleanup to ensure no browser processes are left running try { await aggressiveCleanup.runPostAnalysisCleanup() } catch (cleanupError) { console.error('āŒ Error in post-cycle cleanup:', cleanupError) } } private async processAnalysisForTrading(analysis: any, symbol: string, timeframe: string): Promise { try { console.log(`šŸŽÆ Processing trading analysis for ${symbol} ${timeframe}...`) // Extract key trading signals from analysis const sentiment = analysis.marketSentiment const confidence = analysis.confidence || 0 const recommendation = analysis.recommendation console.log(`šŸ“Š Sentiment: ${sentiment}, Recommendation: ${recommendation}, Confidence: ${confidence}%`) if (analysis.keyLevels) { console.log(`šŸ“ˆ Support levels: ${analysis.keyLevels.support.join(', ')}`) console.log(`šŸ“‰ Resistance levels: ${analysis.keyLevels.resistance.join(', ')}`) } // Trading decision logic if (confidence >= 70) { if (sentiment === 'BULLISH' && recommendation === 'BUY') { console.log('🟢 HIGH CONFIDENCE BULLISH - Consider long position') // await this.executeLongTrade(symbol, timeframe, analysis) } else if (sentiment === 'BEARISH' && recommendation === 'SELL') { console.log('šŸ”“ HIGH CONFIDENCE BEARISH - Consider short position') // await this.executeShortTrade(symbol, timeframe, analysis) } } else if (confidence >= 50) { console.log('🟔 MODERATE CONFIDENCE - Monitor for confirmation') } else { console.log('⚪ LOW CONFIDENCE - Hold current positions') } } catch (error) { console.error('āŒ Error processing trading analysis:', error) } } // Example trading execution methods (implement with your preferred exchange) private async executeLongTrade(symbol: string, timeframe: string, analysis: any): Promise { console.log(`🟢 Executing LONG trade for ${symbol} based on ${timeframe} analysis`) // Implement actual trading logic here // This could use Drift Protocol, Jupiter DEX, or other trading interfaces } private async executeShortTrade(symbol: string, timeframe: string, analysis: any): Promise { console.log(`šŸ”“ Executing SHORT trade for ${symbol} based on ${timeframe} analysis`) // Implement actual trading logic here } // Status methods getStatus() { return { isRunning: this.isRunning, currentCycle: this.currentCycle, config: this.config } } getCurrentCycle(): number { return this.currentCycle } isServiceRunning(): boolean { return this.isRunning } } // Example usage configurations export const TRADING_CONFIGS = { // Scalping configuration - frequent analysis of short timeframes scalping: { symbol: 'SOLUSD', timeframes: ['5m', '15m'], layouts: ['ai', 'diy'], intervalMs: 5 * 60 * 1000, // Every 5 minutes maxCycles: 100 // Limit for testing }, // Day trading configuration - moderate frequency on intraday timeframes dayTrading: { symbol: 'SOLUSD', timeframes: ['1h', '4h'], layouts: ['ai', 'diy'], intervalMs: 30 * 60 * 1000, // Every 30 minutes maxCycles: 50 // Limit for testing }, // Swing trading configuration - less frequent analysis of longer timeframes swingTrading: { symbol: 'SOLUSD', timeframes: ['4h', '1d'], layouts: ['ai', 'diy'], intervalMs: 2 * 60 * 60 * 1000, // Every 2 hours maxCycles: 24 // Limit for testing } } // Singleton instance export const autoTradingService = new AutoTradingService() // Example startup function export async function startTradingBot(configName: keyof typeof TRADING_CONFIGS = 'dayTrading') { const config = TRADING_CONFIGS[configName] if (!config) { throw new Error(`Unknown trading configuration: ${configName}`) } console.log(`šŸš€ Starting trading bot with ${configName} configuration`) await autoTradingService.start(config) } // Graceful shutdown export async function stopTradingBot() { console.log('šŸ›‘ Stopping trading bot...') await autoTradingService.stop() }