Mengambil data dari suatu coin.
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 <coin_symbol>
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 };