#!/usr/bin/env node /** * Host-based 24/7 Trading Automation * Runs on the host system, not inside the container */ const https = require('https'); const http = require('http'); class HostAutomation { constructor() { this.config = { symbol: 'SOLUSD', timeframe: '60', intervalMinutes: 60, autoExecuteThreshold: 60, apiHost: 'localhost:9001', requestTimeout: 30000 }; this.stats = { startTime: new Date(), totalCycles: 0, totalTrades: 0, successfulCycles: 0, failedCycles: 0, lastSignal: null, lastTrade: null }; } async log(message) { const timestamp = new Date().toISOString(); console.log(`[${timestamp}] ${message}`); } async makeRequest(url, options = {}) { return new Promise((resolve, reject) => { const isHttps = url.startsWith('https'); const client = isHttps ? https : http; const requestOptions = { timeout: this.config.requestTimeout, ...options }; const req = client.request(url, requestOptions, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const parsed = JSON.parse(data); resolve(parsed); } catch (e) { resolve({ success: false, error: 'Invalid JSON response' }); } }); }); req.on('error', (error) => { this.log(`❌ Request error: ${error.message}`); resolve(null); }); req.on('timeout', () => { this.log(`⏱️ Request timeout: ${url}`); req.destroy(); resolve(null); }); if (options.body) { req.write(options.body); } req.end(); }); } async makePostRequest(url, data) { return new Promise((resolve, reject) => { const postData = JSON.stringify(data); const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) }, timeout: this.config.requestTimeout }; const req = http.request(url, options, (res) => { let responseData = ''; res.on('data', chunk => responseData += chunk); res.on('end', () => { try { const parsed = JSON.parse(responseData); resolve(parsed); } catch (e) { resolve({ success: false, error: 'Invalid JSON response' }); } }); }); req.on('error', (error) => { this.log(`❌ POST request error: ${error.message}`); resolve(null); }); req.on('timeout', () => { this.log(`⏱️ POST request timeout: ${url}`); req.destroy(); resolve(null); }); req.write(postData); req.end(); }); } async runAnalysisCycle() { this.stats.totalCycles++; await this.log(`🔄 Analysis cycle #${this.stats.totalCycles}`); try { await this.log(`📡 Fetching analysis from API...`); const data = await this.makeRequest(`http://${this.config.apiHost}/api/ai-analysis/latest?symbol=${this.config.symbol}&timeframe=${this.config.timeframe}`); if (data && data.success && data.data && data.data.analysis) { const analysis = data.data.analysis; this.stats.lastSignal = { time: new Date(), recommendation: analysis.recommendation, confidence: analysis.confidence }; await this.log(`📊 Signal: ${analysis.recommendation} (${analysis.confidence}% confidence)`); if (analysis.confidence >= this.config.autoExecuteThreshold && (analysis.recommendation === 'BUY' || analysis.recommendation === 'SELL')) { await this.log(`🚀 Executing ${analysis.recommendation} trade with ${analysis.confidence}% confidence`); const trade = await this.executeTrade(analysis); if (trade && trade.success) { this.stats.totalTrades++; this.stats.lastTrade = { time: new Date(), type: analysis.recommendation, confidence: analysis.confidence, price: trade.trade?.entry || analysis.entry?.price || 'unknown' }; await this.log(`✅ Trade executed: ${analysis.recommendation} at ${trade.trade?.entry || analysis.entry?.price}`); } else { await this.log(`❌ Trade execution failed`); } } else { await this.log(`⏸️ Confidence ${analysis.confidence}% below threshold ${this.config.autoExecuteThreshold}% - holding`); } this.stats.successfulCycles++; } else { await this.log(`❌ No valid analysis data received`); this.stats.failedCycles++; } } catch (error) { await this.log(`❌ Cycle error: ${error.message}`); this.stats.failedCycles++; } await this.printStats(); const nextCycle = new Date(Date.now() + this.config.intervalMinutes * 60 * 1000); await this.log(`⏰ Next cycle: ${nextCycle.toLocaleTimeString()}`); setTimeout(() => this.runAnalysisCycle(), this.config.intervalMinutes * 60 * 1000); } async executeTrade(analysis) { try { await this.log(`💱 Preparing trade data...`); const tradeData = { symbol: this.config.symbol, side: analysis.recommendation, amount: 100, entry: analysis.entry?.price || 150, confidence: analysis.confidence, reasoning: analysis.reasoning || 'Automated trade', source: 'host_automation_24x7' }; await this.log(`📤 Sending trade request...`); const result = await this.makePostRequest(`http://${this.config.apiHost}/api/safe-paper-trading/create-trade`, tradeData); return result; } catch (error) { await this.log(`❌ Trade execution error: ${error.message}`); return null; } } async printStats() { const uptime = Math.floor((Date.now() - this.stats.startTime) / 1000 / 60); const successRate = this.stats.totalCycles > 0 ? Math.round((this.stats.successfulCycles / this.stats.totalCycles) * 100) : 0; await this.log(`📈 Stats: ${this.stats.totalCycles} cycles (${successRate}% success), ${this.stats.totalTrades} trades, ${uptime}m uptime`); if (this.stats.lastSignal) { const signalAge = Math.floor((Date.now() - this.stats.lastSignal.time) / 1000 / 60); await this.log(`🎯 Last signal: ${this.stats.lastSignal.recommendation} (${this.stats.lastSignal.confidence}%) ${signalAge}m ago`); } if (this.stats.lastTrade) { const tradeAge = Math.floor((Date.now() - this.stats.lastTrade.time) / 1000 / 60); await this.log(`💰 Last trade: ${this.stats.lastTrade.type} at ${this.stats.lastTrade.price} ${tradeAge}m ago`); } } async start() { await this.log('🚀 Host-based 24/7 Trading Automation Started'); await this.log(`📊 Config: ${this.config.symbol} every ${this.config.intervalMinutes}m, threshold: ${this.config.autoExecuteThreshold}%`); await this.log(`🌐 API Host: ${this.config.apiHost}`); await this.runAnalysisCycle(); } } const automation = new HostAutomation(); automation.start().catch(error => { console.error('💥 Automation failed to start:', error); process.exit(1); });