const axios = require('axios'); class RealTimeCryptoAnalyzer { constructor() { this.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'application/json', 'Accept-Language': 'id-ID,id;q=0.9,en;q=0.8' }; this.axiosInstance = axios.create({ timeout: 30000, headers: this.headers }); this.coinIds = { 'btc': 'bitcoin', 'eth': 'ethereum', 'bnb': 'binancecoin', 'xrp': 'ripple', 'ada': 'cardano', 'doge': 'dogecoin', 'sol': 'solana', 'dot': 'polkadot', 'matic': 'matic-network', 'avax': 'avalanche-2', 'ltc': 'litecoin', 'link': 'chainlink', 'atom': 'cosmos', 'uni': 'uniswap', 'trx': 'tron' }; } formatDate(date) { return date.toLocaleDateString('id-ID') + ', ' + date.toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }); } calculateMA(prices, period) { if (prices.length < period) return null; const sum = prices.slice(-period).reduce((a, b) => a + b, 0); return sum / period; } calculateRSI(prices, period = 14) { if (prices.length < period + 1) return 50; let gains = 0; let losses = 0; for (let i = 1; i <= period; i++) { const change = prices[prices.length - i] - prices[prices.length - i - 1]; if (change > 0) { gains += change; } else { losses -= change; } } const avgGain = gains / period; const avgLoss = losses / period; if (avgLoss === 0) return 100; const rs = avgGain / avgLoss; return 100 - (100 / (1 + rs)); } generateSignal(price, ma5, ma10, rsi) { if (!ma5 || !ma10) return "DATA TIDAK CUKUP"; if (price > ma5 && price > ma10 && rsi > 70) { return "OVERSOLD - JUAL"; } else if (price < ma5 && price < ma10 && rsi < 30) { return "OVERSOLD - BELI"; } else if (price > ma5 && rsi > 60) { return "TREN NAIK - HOLD"; } else if (price < ma5 && rsi < 40) { return "TREN TURUN - HOLD"; } else if (rsi > 50 && price > ma5) { return "BULLISH - TUNGGU"; } else if (rsi < 50 && price < ma5) { return "BEARISH - TUNGGU"; } else { return "SIDEWAYS - HOLD"; } } async getRealTimePrice(coin) { try { const coinId = this.coinIds[coin.toLowerCase()]; if (!coinId) { throw new Error(`Coin ${coin} tidak dikenali`); } // CoinGecko API const response = await this.axiosInstance.get( `https://api.coingecko.com/api/v3/coins/${coinId}?localization=false&tickers=false&market_data=true&community_data=false&developer_data=false&sparkline=false` ); const data = response.data; const priceIDR = data.market_data.current_price.idr; return { price: priceIDR, name: data.name, symbol: data.symbol.toUpperCase(), change24h: data.market_data.price_change_percentage_24h, high24h: data.market_data.high_24h.idr, low24h: data.market_data.low_24h.idr }; } catch (error) { console.log('CoinGecko gagal, mencoba API alternatif...'); return await this.getAlternativePrice(coin); } } async getAlternativePrice(coin) { try { // Binance API sebagai alternatif const symbol = `${coin.toUpperCase()}USDT`; const response = await this.axiosInstance.get( `https://api.binance.com/api/v3/ticker/24hr?symbol=${symbol}` ); const data = response.data; const usdPrice = parseFloat(data.lastPrice); // Konversi USD ke IDR (kurs tetap untuk simulasi) const usdToIdr = 16000; const priceIDR = usdPrice * usdToIdr; return { price: priceIDR, name: coin.toUpperCase(), symbol: coin.toUpperCase(), change24h: parseFloat(data.priceChangePercent), high24h: parseFloat(data.highPrice) * usdToIdr, low24h: parseFloat(data.lowPrice) * usdToIdr }; } catch (error) { throw new Error(`Tidak bisa mendapatkan harga real-time untuk ${coin}`); } } async getHistoricalData(coin, days = 15) { try { const coinId = this.coinIds[coin.toLowerCase()]; const response = await this.axiosInstance.get( `https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=idr&days=${days}&interval=daily` ); const prices = response.data.prices; const historicalData = []; prices.forEach(([timestamp, price]) => { const date = new Date(timestamp); historicalData.push({ date: this.formatDate(date), price: price }); }); return historicalData; } catch (error) { console.log('Gagal mengambil data historis, menggunakan data simulasi...'); return this.generateSimulatedData(coin, days); } } generateSimulatedData(coin, days) { const data = []; const basePrice = this.getBasePrice(coin); const volatility = this.getVolatility(coin); const startDate = new Date(); startDate.setDate(startDate.getDate() - days); let currentPrice = basePrice; for (let i = 0; i < days; i++) { const date = new Date(startDate); date.setDate(date.getDate() + i); const randomChange = (Math.random() - 0.5) * 2 * volatility; currentPrice = currentPrice * (1 + randomChange / 100); data.push({ date: this.formatDate(date), price: Math.round(currentPrice * 100) / 100 }); } return data; } getBasePrice(coin) { const basePrices = { 'btc': 900000000, 'eth': 60000000, 'bnb': 8000000, 'xrp': 8000, 'ada': 5000, 'doge': 3000, 'sol': 2000000, 'dot': 50000, 'matic': 4000, 'avax': 150000, 'ltc': 1200000, 'link': 120000, 'atom': 120000, 'uni': 60000, 'trx': 1000 }; return basePrices[coin.toLowerCase()] || 1000000; } getVolatility(coin) { const volatilities = { 'btc': 2, 'eth': 3, 'bnb': 4, 'xrp': 5, 'ada': 6, 'doge': 8, 'sol': 7, 'dot': 5, 'matic': 6, 'avax': 7, 'ltc': 4, 'link': 6, 'atom': 5, 'uni': 7, 'trx': 8 }; return volatilities[coin.toLowerCase()] || 5; } async getCryptoData(coin) { try { console.log(`🔄 Mengambil data real-time untuk ${coin.toUpperCase()}...`); const realTimeData = await this.getRealTimePrice(coin); const historicalData = await this.getHistoricalData(coin); const prices = historicalData.map(item => item.price); prices.push(realTimeData.price); // Tambahkan harga terbaru const ma5 = this.calculateMA(prices, 5); const ma10 = this.calculateMA(prices, 10); const rsi = this.calculateRSI(prices); const signal = this.generateSignal(realTimeData.price, ma5, ma10, rsi); return { status: true, creator: "Hazel", result: { coin: coin.toLowerCase(), name: realTimeData.name, symbol: realTimeData.symbol, update: this.formatDate(new Date()), price: realTimeData.price, change24h: realTimeData.change24h, high24h: realTimeData.high24h, low24h: realTimeData.low24h, ma5: ma5 ? Math.round(ma5 * 100) / 100 : null, ma10: ma10 ? Math.round(ma10 * 100) / 100 : null, rsi: Math.round(rsi * 100) / 100, signal: signal, chart: historicalData } }; } catch (error) { return { status: false, error: error.message }; } } } class SimpleCryptoAnalyzer { constructor() { this.analyzer = new RealTimeCryptoAnalyzer(); } async analyze(coin) { try { if (!coin || typeof coin !== 'string') { return JSON.stringify({ status: false, error: 'Coin tidak valid' }, null, 2); } const result = await this.analyzer.getCryptoData(coin); return JSON.stringify(result, null, 2); } catch (error) { return JSON.stringify({ status: false, error: error.message }, null, 2); } } } async function main() { const args = process.argv.slice(2); if (args.length === 0) { console.log(` 💰 Real-Time Crypto Analyzer Usage: node crypto.js Supported coins: BTC, ETH, BNB, XRP, ADA, DOGE, SOL, DOT, MATIC, AVAX LTC, LINK, ATOM, UNI, TRX Examples: node crypto.js btc node crypto.js eth node crypto.js sol `); return; } const coin = args[0]; const analyzer = new SimpleCryptoAnalyzer(); try { const result = await analyzer.analyze(coin); console.log(result); } catch (error) { console.log(JSON.stringify({ status: false, error: error.message }, null, 2)); } } if (require.main === module) { main(); } module.exports = { RealTimeCryptoAnalyzer, SimpleCryptoAnalyzer };