class SafeParallelAutomation { private isRunning = false private config: any = null private intervalId: NodeJS.Timeout | null = null private lastAnalysisTime = 0 // SAFE PARAMETERS - Respect timeframe strategy private readonly MIN_ANALYSIS_INTERVAL = 10 * 60 * 1000 // 10 minutes minimum private readonly MAX_TRADES_PER_HOUR = 2 private readonly ANALYSIS_COOLDOWN = 5 * 60 * 1000 // 5 minutes private stats = { totalTrades: 0, successfulTrades: 0, winRate: 0, totalPnL: 0, errorCount: 0, lastAnalysis: null as string | null, nextScheduled: null as string | null, nextAnalysisIn: 0, analysisInterval: 0, currentCycle: 0, lastError: null as string | null, strategyType: 'General' } async startSafeAutomation(config: any): Promise<{ success: boolean, message?: string }> { try { if (this.isRunning) { return { success: false, message: 'Safe automation already running' } } // SAFETY CHECK: Rate limiting const now = Date.now() if (now - this.lastAnalysisTime < this.ANALYSIS_COOLDOWN) { const remaining = Math.ceil((this.ANALYSIS_COOLDOWN - (now - this.lastAnalysisTime)) / 1000) return { success: false, message: 'Safety cooldown: Wait ' + remaining + ' seconds' } } // SAFETY CHECK: Validate timeframes if (!config.timeframes || config.timeframes.length === 0) { return { success: false, message: 'At least one timeframe required' } } this.config = config this.isRunning = true this.lastAnalysisTime = now this.stats.currentCycle = 0 this.stats.strategyType = config.strategyType || 'General' console.log('SAFE PARALLEL: Starting for ' + config.symbol) console.log('STRATEGY: ' + this.stats.strategyType) console.log('TIMEFRAMES: [' + config.timeframes.join(', ') + ']') console.log('SAFETY: Max ' + this.MAX_TRADES_PER_HOUR + ' trades/hour') // Start with strategy-appropriate interval this.startSafeAnalysisCycle() return { success: true, message: 'Safe parallel automation started' } } catch (error) { console.error('Failed to start safe automation:', error) return { success: false, message: 'Failed to start automation' } } } private startSafeAnalysisCycle(): void { // Get strategy-appropriate interval but enforce minimum safety const strategyInterval = this.getStrategyInterval(this.config.timeframes, this.config.strategyType) const safeInterval = Math.max(this.MIN_ANALYSIS_INTERVAL, strategyInterval) console.log('STRATEGY INTERVAL: ' + (strategyInterval / 1000 / 60) + ' minutes') console.log('SAFE INTERVAL: ' + (safeInterval / 1000 / 60) + ' minutes (enforced minimum)') this.stats.analysisInterval = safeInterval this.stats.nextScheduled = new Date(Date.now() + safeInterval).toISOString() this.stats.nextAnalysisIn = safeInterval // Set safe interval this.intervalId = setInterval(async () => { if (this.isRunning && this.config) { await this.runSafeAnalysisCycle() } }, safeInterval) // First cycle after delay setTimeout(() => { if (this.isRunning && this.config) { this.runSafeAnalysisCycle() } }, 30000) } private async runSafeAnalysisCycle(): Promise { try { console.log('\nSAFE CYCLE ' + (this.stats.currentCycle + 1) + ': ' + this.config.symbol) console.log('STRATEGY: ' + this.stats.strategyType) // SAFETY CHECK const canTrade = await this.canExecuteTrade() if (!canTrade.allowed) { console.log('SAFETY BLOCK: ' + canTrade.reason) this.updateNextAnalysisTime() return } // PARALLEL ANALYSIS using enhanced screenshot API console.log('PARALLEL: Analyzing ' + this.config.timeframes.length + ' timeframes...') const analysisResult = await this.performParallelAnalysis() if (!analysisResult || !analysisResult.analysis) { console.log('Analysis failed, skipping') return } this.stats.lastAnalysis = new Date().toISOString() console.log('ANALYSIS: ' + analysisResult.analysis.recommendation) // CONTROLLED TRADING with strategy-specific logic if (this.shouldExecuteTrade(analysisResult.analysis)) { console.log('EXECUTING: Trade criteria met for ' + this.stats.strategyType) const tradeResult = await this.executeSafeTrade(analysisResult.analysis) if (tradeResult?.success) { this.stats.totalTrades++ this.stats.successfulTrades++ this.stats.winRate = (this.stats.successfulTrades / this.stats.totalTrades) * 100 console.log('TRADE: Executed successfully') } } else { console.log('SIGNAL: Criteria not met for ' + this.stats.strategyType) } this.stats.currentCycle++ } catch (error) { console.error('Error in safe cycle:', error) this.stats.errorCount++ this.stats.lastError = error instanceof Error ? error.message : 'Unknown error' } finally { await this.guaranteedCleanup() this.updateNextAnalysisTime() } } private async performParallelAnalysis(): Promise { try { // Use the enhanced screenshot API endpoint with all selected timeframes const response = await fetch('http://localhost:3000/api/enhanced-screenshot', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ symbol: this.config.symbol, timeframes: this.config.timeframes, layouts: ['ai', 'diy'], analyze: true }) }) throw new Error('API response: ' + response.status) } const result = await response.json() if (result.analysis) { console.log('PARALLEL: Confidence ' + result.analysis.confidence + '%') return result } return null } catch (error) { console.error('Error in parallel analysis:', error) throw error } } private shouldExecuteTrade(analysis: any): boolean { const recommendation = analysis.recommendation.toLowerCase() const confidence = analysis.confidence || 0 // Strategy-specific confidence requirements let minConfidence = 75 // Default if (this.stats.strategyType === 'Scalping') { minConfidence = 80 // Higher confidence for scalping } else if (this.stats.strategyType === 'Day Trading') { minConfidence = 75 // Standard confidence } else if (this.stats.strategyType === 'Swing Trading') { minConfidence = 70 // Slightly lower for swing (longer timeframes) } const isHighConfidence = confidence >= minConfidence const isClearDirection = recommendation.includes('buy') || recommendation.includes('sell') console.log('SIGNAL: ' + recommendation + ' (' + confidence + '%) - Required: ' + minConfidence + '%') return isHighConfidence && isClearDirection } private getStrategyInterval(timeframes: string[], strategyType: string): number { // Strategy-based intervals (but minimum will be enforced) if (strategyType === 'Scalping') { console.log('SCALPING: Using 2-minute analysis cycle') return 2 * 60 * 1000 // 2 minutes for scalping (will be enforced to 10 min minimum) } if (strategyType === 'Day Trading') { console.log('DAY TRADING: Using 5-minute analysis cycle') return 5 * 60 * 1000 // 5 minutes for day trading (will be enforced to 10 min minimum) } if (strategyType === 'Swing Trading') { console.log('SWING TRADING: Using 15-minute analysis cycle') return 15 * 60 * 1000 // 15 minutes for swing trading } // Fallback based on shortest timeframe const shortest = Math.min(...timeframes.map(tf => { if (tf === 'D') return 1440 return parseInt(tf) || 60 })) if (shortest <= 5) return 2 * 60 * 1000 // 2 min for very short if (shortest <= 15) return 5 * 60 * 1000 // 5 min for short if (shortest <= 60) return 10 * 60 * 1000 // 10 min for medium return 15 * 60 * 1000 // 15 min for long } private async executeSafeTrade(analysis: any): Promise { try { console.log('SAFE TRADE: Executing...') // Use drift trading API endpoint const response = await fetch('http://localhost:3000/api/trading', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mode: this.config.mode, symbol: this.config.symbol, amount: this.config.tradingAmount, leverage: this.config.leverage, stopLoss: this.config.stopLoss, takeProfit: this.config.takeProfit, analysis: analysis, strategy: this.stats.strategyType }) }) const result = await response.json() return result } catch (error) { console.error('Error executing trade:', error) return { success: false, error: error.message } } } private async canExecuteTrade(): Promise<{ allowed: boolean, reason?: string }> { const now = Date.now() if (now - this.lastAnalysisTime < this.ANALYSIS_COOLDOWN) { const remaining = Math.ceil((this.ANALYSIS_COOLDOWN - (now - this.lastAnalysisTime)) / 1000 / 60) return { allowed: false, reason: 'Cooldown: ' + remaining + 'min' } } if (this.stats.totalTrades >= this.MAX_TRADES_PER_HOUR) { return { allowed: false, reason: 'Hour limit: ' + this.stats.totalTrades + '/' + this.MAX_TRADES_PER_HOUR } } return { allowed: true } } private async guaranteedCleanup(): Promise { try { const { execSync } = require('child_process') execSync('pkill -f "chrome|chromium" 2>/dev/null || true') console.log('CLEANUP: Completed') } catch (error) { console.error('CLEANUP: Failed', error) } } private updateNextAnalysisTime(): void { const nextTime = Date.now() + this.stats.analysisInterval this.stats.nextScheduled = new Date(nextTime).toISOString() this.stats.nextAnalysisIn = this.stats.analysisInterval } async stopSafeAutomation(): Promise<{ success: boolean, message?: string }> { try { this.isRunning = false if (this.intervalId) { clearInterval(this.intervalId) this.intervalId = null } await this.guaranteedCleanup() this.config = null this.stats.nextAnalysisIn = 0 this.stats.nextScheduled = null console.log('SAFE: Automation stopped') return { success: true, message: 'Safe automation stopped' } } catch (error) { return { success: false, message: 'Stop failed' } } } getStatus() { return { isActive: this.isRunning, mode: this.config?.mode || 'SIMULATION', symbol: this.config?.symbol || 'SOLUSD', timeframes: this.config?.timeframes || ['1h'], automationType: 'SAFE_PARALLEL', strategy: this.stats.strategyType, ...this.stats } } } export const safeParallelAutomation = new SafeParallelAutomation()