const axios = require('axios'); const fs = require('fs'); const { SocksProxyAgent } = require('socks-proxy-agent'); const logger = require('./utils/logger') const BASE_REST = 'https://api.binance.com' const QUOTE_ASSET = 'USDT' // 拉取什么交易对的 const NUMBER_OF_DAYS_TO_PULL = 144 // 一共拉取多少K的数据 const socksProxy = 'socks://127.0.0.1:7890'; const agent = new SocksProxyAgent(socksProxy); async function HttpQuery(url) { try { let rst = await axios.get(url, { httpAgent: agent, httpsAgent: agent }) return rst.data } catch (error) { // 请求失败,处理错误 if (error.response) { // 服务器返回了响应,并且响应中包含了错误信息 logger.error('Error url:', url) logger.error('Error data:', error.response.data); logger.error('Error status:', error.response.status); logger.error('Error headers:', error.response.headers); } else if (error.request) { // 请求已发出,但没有收到响应 logger.error('No response received:', error.request); } else { // 设置请求时发生了一些问题 logger.error('Error message:', error.message); } // 打印错误的配置信息(可选) logger.error('Error config:', error.config); return undefined } } async function main() { const exchangeInfo = await HttpQuery(`${BASE_REST}/api/v3/exchangeInfo?permissions=SPOT`) const symbolsInfo = exchangeInfo.symbols.filter((item) => { return item.quoteAsset === QUOTE_ASSET && item.symbol.endsWith(QUOTE_ASSET) && item.status === 'TRADING' }) // const symbols = symbolsInfo.slice(0, 10).map((item) => item.symbol.replace(QUOTE_ASSET, `_${QUOTE_ASSET}`)) const symbols = symbolsInfo.map((item) => item.symbol.replace(QUOTE_ASSET, `_${QUOTE_ASSET}`)) let kLinesMap = {} // TODO 有空接一下期货的 for (let i = 0; i < symbols.length; i++) { let symbol = symbols[i] // let url = `${BASE_REST}/api/v3/klines?symbol=${symbol.replace('_', '')}&interval=2h&limit=${NUMBER_OF_DAYS_TO_PULL}&startTime=1636560000000` let url = `${BASE_REST}/api/v3/klines?symbol=${symbol.replace('_', '')}&interval=2h&limit=${NUMBER_OF_DAYS_TO_PULL}` const kLines = await HttpQuery(url) kLinesMap[symbol] = [] for (let kLine of kLines) { kLinesMap[symbol].push({ Symbol: symbol, Time: kLine[0], Open: parseFloat(kLine[1]), High: parseFloat(kLine[2]), Low: parseFloat(kLine[3]), Close: parseFloat(kLine[4]), Volume: parseFloat(kLine[5]), Turnover: parseFloat(kLine[7]), // 成交额 NumberOfTx: kLine[8], // 成交笔数 BuyVolume: parseFloat(kLine[9]), // 主动买入成交量 BuyTurnover: parseFloat(kLine[10]), // 主动买入成交额 }) } // length - 1是最新一天的 logger.info(`${symbol}拉取完毕,拉取到${kLinesMap[symbol].length}条(${i+1}/${symbols.length})。`) // await TimeKit.sleep(1000) } fs.writeFile('./data/k_lines.json', JSON.stringify(kLinesMap, null, 2), 'utf8', (err) => { if (err) { logger.error('写入文件时发生错误:', err); } else { logger.info('JSON 数据已保存到 ./data/k_lines.json'); } }); } main().catch((error) => { logger.error(error.stack); process.exitCode = 1; })