UNPKG

@gabriel3615/ta_analysis

Version:

stock ta analysis

81 lines (80 loc) 2.79 kB
function mapInterval(interval) { if (interval === '1h') return '1h'; if (interval === '1d') return '1d'; return '1w'; } function intervalMs(interval) { if (interval === '1h') return 60 * 60 * 1000; if (interval === '1d') return 24 * 60 * 60 * 1000; return 7 * 24 * 60 * 60 * 1000; } function normalizeSpotSymbol(input) { if (!input) return input; const s = String(input).trim().toUpperCase(); if (s.includes('-') || s.includes('/')) { const [base, rawQuote] = s.split(/[-/]/); const quote = rawQuote === 'USD' ? 'USDT' : rawQuote; return `${base}${quote}`; } return s; } export class BinanceProvider { constructor() { this.baseUrl = 'https://api.binance.com'; } async getKlines(symbol, interval, startTime, endTime) { const normSymbol = normalizeSpotSymbol(symbol); const iv = mapInterval(interval); const step = intervalMs(interval); const limit = 1000; // Binance max const result = []; let from = startTime.getTime(); const end = endTime.getTime(); while (from < end) { const params = new URLSearchParams({ symbol: normSymbol, interval: iv, startTime: String(from), endTime: String(end), limit: String(limit), }); const url = `${this.baseUrl}/api/v3/klines?${params.toString()}`; const res = await fetch(url); if (!res.ok) break; const arr = await res.json(); if (!Array.isArray(arr) || arr.length === 0) break; for (const row of arr) { const openTime = Number(row[0]); if (openTime >= from && openTime <= end) { result.push({ symbol: normSymbol, open: Number(row[1]), high: Number(row[2]), low: Number(row[3]), close: Number(row[4]), volume: Number(row[5]), timestamp: new Date(openTime), }); } } const last = Number(arr[arr.length - 1]?.[0]); const next = Math.max(from + step, last + step); if (next <= from) break; // safety from = next; // 小等待以避免突发速率(通常无需) if (arr.length >= limit) await new Promise(r => setTimeout(r, 100)); } // 排序保证升序 result.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime()); return result; } }