/** * 🌍 Multi-Asset Global Market Automation * * Features: * - Multiple crypto assets (SOL, BTC, ETH, etc.) * - Cross-asset correlation analysis * - Global sentiment integration * - Portfolio-based position sizing * - Market regime detection */ const https = require('https'); class MultiAssetGlobalTrader { constructor() { this.assets = [ { symbol: 'SOLUSD', weight: 0.4, minConfidence: 60 }, { symbol: 'BTCUSD', weight: 0.3, minConfidence: 65 }, { symbol: 'ETHUSD', weight: 0.2, minConfidence: 60 }, { symbol: 'ADAUSD', weight: 0.1, minConfidence: 70 } ]; this.portfolioRisk = 0.02; // 2% total portfolio risk this.correlationThreshold = 0.7; // Reduce size if high correlation this.cycleCount = 0; this.lastAnalysis = {}; this.portfolioMetrics = {}; } async log(message) { const timestamp = new Date().toISOString(); console.log(`[${timestamp}] ${message}`); } async makeRequest(url, options = {}) { return new Promise((resolve, reject) => { const req = https.request(url, options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { resolve(res.statusCode === 200 ? JSON.parse(data) : null); } catch (e) { resolve(null); } }); }); req.on('error', reject); if (options.method === 'POST' && options.body) { req.write(JSON.stringify(options.body)); } req.end(); }); } async getGlobalSentiment() { try { // Get comprehensive sentiment data const [fearGreed, btcPrice, ethPrice, solPrice] = await Promise.all([ this.getFearGreedIndex(), this.getAssetPrice('bitcoin'), this.getAssetPrice('ethereum'), this.getAssetPrice('solana') ]); const sentiment = { fearGreed: fearGreed || this.estimateFearGreed(), btcDominance: this.calculateBtcDominance(btcPrice, ethPrice, solPrice), marketRegime: 'UNKNOWN', riskLevel: 'MODERATE', correlationLevel: 'NORMAL' }; // Determine market regime if (sentiment.fearGreed.value <= 25) { sentiment.marketRegime = 'EXTREME_FEAR'; sentiment.riskLevel = 'HIGH_OPPORTUNITY'; } else if (sentiment.fearGreed.value <= 45) { sentiment.marketRegime = 'FEAR'; sentiment.riskLevel = 'MODERATE_OPPORTUNITY'; } else if (sentiment.fearGreed.value >= 75) { sentiment.marketRegime = 'EXTREME_GREED'; sentiment.riskLevel = 'HIGH_RISK'; } else if (sentiment.fearGreed.value >= 55) { sentiment.marketRegime = 'GREED'; sentiment.riskLevel = 'MODERATE_RISK'; } else { sentiment.marketRegime = 'NEUTRAL'; sentiment.riskLevel = 'BALANCED'; } return sentiment; } catch (error) { await this.log(`❌ Sentiment error: ${error.message}`); return this.getDefaultSentiment(); } } async getFearGreedIndex() { try { const response = await this.makeRequest('https://api.alternative.me/fng/'); if (response?.data?.[0]) { const data = response.data[0]; return { value: parseInt(data.value), classification: data.value_classification, timestamp: data.timestamp }; } } catch (error) { await this.log(`πŸ“Š Fear & Greed API blocked, using estimation`); } return null; } async getAssetPrice(coinId) { try { const url = `https://api.coingecko.com/api/v3/simple/price?ids=${coinId}&vs_currencies=usd&include_24hr_change=true`; const response = await this.makeRequest(url); return response?.[coinId]; } catch (error) { return null; } } calculateBtcDominance(btcPrice, ethPrice, solPrice) { // Simplified dominance calculation if (!btcPrice || !ethPrice || !solPrice) return 50; const btcCap = btcPrice.usd * 19.7e6; // ~19.7M BTC const ethCap = ethPrice.usd * 120e6; // ~120M ETH const solCap = solPrice.usd * 580e6; // ~580M SOL const totalCap = btcCap + ethCap + solCap; return Math.round((btcCap / totalCap) * 100); } estimateFearGreed() { // Estimate based on price action const now = Date.now(); const baseValue = 50 + Math.sin(now / (1000 * 60 * 60 * 24)) * 25; return { value: Math.round(Math.max(0, Math.min(100, baseValue))), classification: 'estimated', timestamp: Math.floor(now / 1000) }; } getDefaultSentiment() { return { fearGreed: { value: 50, classification: 'neutral' }, btcDominance: 50, marketRegime: 'NEUTRAL', riskLevel: 'MODERATE', correlationLevel: 'NORMAL' }; } async analyzeAsset(asset, sentiment) { try { await this.log(`πŸ” Analyzing ${asset.symbol}...`); const analysisUrl = `http://localhost:3000/api/ai-analysis/latest?symbol=${asset.symbol}&timeframe=240`; const response = await this.makeRequest(analysisUrl); if (!response?.data?.analysis) { throw new Error('No analysis data received'); } const analysis = response.data.analysis; // Adjust confidence based on sentiment const adjustedConfidence = this.adjustConfidenceForSentiment( analysis.confidence, sentiment, asset ); return { ...analysis, originalConfidence: analysis.confidence, adjustedConfidence, sentimentImpact: adjustedConfidence - analysis.confidence, asset: asset.symbol, weight: asset.weight }; } catch (error) { await this.log(`❌ Analysis failed for ${asset.symbol}: ${error.message}`); return null; } } adjustConfidenceForSentiment(confidence, sentiment, asset) { let adjustment = 0; // Fear & Greed adjustments if (sentiment.fearGreed.value <= 25) { // Extreme fear = more bullish bias adjustment += confidence > 50 ? 10 : -5; } else if (sentiment.fearGreed.value >= 75) { // Extreme greed = more bearish bias adjustment += confidence < 50 ? 10 : -5; } // BTC dominance impact (mainly for altcoins) if (asset.symbol !== 'BTCUSD' && sentiment.btcDominance > 60) { // High BTC dom = bearish for alts adjustment -= 5; } else if (asset.symbol !== 'BTCUSD' && sentiment.btcDominance < 40) { // Low BTC dom = bullish for alts adjustment += 5; } return Math.max(0, Math.min(100, confidence + adjustment)); } async calculatePortfolioPositions(analyses, sentiment) { const positions = []; let totalRisk = 0; for (const analysis of analyses) { if (!analysis) continue; const asset = this.assets.find(a => a.symbol === analysis.asset); if (!asset) continue; // Check if confidence meets threshold if (analysis.adjustedConfidence < asset.minConfidence) { await this.log(`⏸️ ${asset.symbol}: Confidence ${analysis.adjustedConfidence.toFixed(1)}% below threshold ${asset.minConfidence}%`); continue; } // Calculate position size based on sentiment let baseSize = this.portfolioRisk * asset.weight; const sentimentMultiplier = this.getSentimentMultiplier(sentiment, analysis); const finalSize = baseSize * sentimentMultiplier; totalRisk += finalSize; positions.push({ symbol: asset.symbol, recommendation: analysis.recommendation, confidence: analysis.adjustedConfidence, originalConfidence: analysis.originalConfidence, sentimentImpact: analysis.sentimentImpact, positionSize: finalSize, sentimentMultiplier, reasoning: analysis.reasoning }); await this.log(`πŸ’Ό ${asset.symbol}: ${analysis.recommendation} at ${analysis.adjustedConfidence.toFixed(1)}% confidence, ${(finalSize*100).toFixed(2)}% portfolio risk`); } await this.log(`πŸ“Š Total portfolio risk: ${(totalRisk*100).toFixed(2)}%`); return positions; } getSentimentMultiplier(sentiment, analysis) { let multiplier = 1.0; // Extreme fear = increase size for good opportunities if (sentiment.fearGreed.value <= 25 && analysis.adjustedConfidence >= 70) { multiplier = 1.5; } // Extreme greed = reduce size else if (sentiment.fearGreed.value >= 75) { multiplier = 0.6; } // Fear = moderate increase for strong signals else if (sentiment.fearGreed.value <= 45 && analysis.adjustedConfidence >= 75) { multiplier = 1.2; } // Greed = moderate decrease else if (sentiment.fearGreed.value >= 55) { multiplier = 0.8; } return multiplier; } async executePortfolioTrades(positions) { for (const position of positions) { try { await this.log(`πŸš€ Executing ${position.symbol}: ${position.recommendation}`); const tradeData = { symbol: position.symbol, recommendation: position.recommendation, confidence: position.confidence, positionSize: position.positionSize, reasoning: `Global sentiment: ${position.reasoning}. Sentiment impact: ${position.sentimentImpact.toFixed(1)}%`, metadata: { globalSentiment: true, sentimentMultiplier: position.sentimentMultiplier, originalConfidence: position.originalConfidence } }; const response = await this.makeRequest('http://localhost:3000/api/safe-paper-trading/create-trade', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: tradeData }); if (response?.success) { await this.log(`βœ… ${position.symbol} trade created: ${response.trade.id}`); } else { await this.log(`❌ ${position.symbol} trade failed: ${response?.error || 'Unknown error'}`); } } catch (error) { await this.log(`❌ Trade execution error for ${position.symbol}: ${error.message}`); } } } async runAnalysisCycle() { this.cycleCount++; await this.log(`\n🌍 === Multi-Asset Global Analysis Cycle #${this.cycleCount} ===`); try { // 1. Get global market sentiment const sentiment = await this.getGlobalSentiment(); await this.log(`πŸ“ˆ Global Sentiment: ${sentiment.marketRegime} | F&G: ${sentiment.fearGreed.value} | BTC Dom: ${sentiment.btcDominance}%`); // 2. Analyze all assets const analyses = await Promise.all( this.assets.map(asset => this.analyzeAsset(asset, sentiment)) ); // 3. Calculate portfolio positions const positions = await this.calculatePortfolioPositions(analyses, sentiment); // 4. Execute trades if any positions qualify if (positions.length > 0) { await this.executePortfolioTrades(positions); } else { await this.log(`⏸️ No trades meet criteria this cycle`); } // 5. Store analysis for correlation tracking this.lastAnalysis = { timestamp: Date.now(), sentiment, analyses: analyses.filter(a => a !== null), positions }; } catch (error) { await this.log(`❌ Analysis cycle error: ${error.message}`); } await this.log(`⏰ Next cycle in 60 minutes...\n`); } async start() { await this.log(`πŸš€ Multi-Asset Global Automation Started`); await this.log(`πŸ“Š Assets: ${this.assets.map(a => `${a.symbol}(${a.weight*100}%)`).join(', ')}`); await this.log(`πŸ“Š Portfolio risk limit: ${this.portfolioRisk*100}%`); // Run initial cycle await this.runAnalysisCycle(); // Schedule regular cycles (60 minutes) setInterval(() => { this.runAnalysisCycle(); }, 60 * 60 * 1000); } } // Start the multi-asset global trader const trader = new MultiAssetGlobalTrader(); trader.start().catch(console.error); module.exports = MultiAssetGlobalTrader;