UNPKG

tardis-dev

Version:

Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js

217 lines (186 loc) 6.31 kB
import { upperCaseSymbols } from '../handy' import { BookChange, BookTicker, DerivativeTicker, Exchange, Trade } from '../types' import { Mapper, PendingTickerInfoHelper } from './mapper' export class BitgetTradesMapper implements Mapper<'bitget' | 'bitget-futures', Trade> { constructor(private readonly _exchange: Exchange) {} canHandle(message: BitgetTradeMessage) { return message.arg.channel === 'trade' && message.action === 'update' } getFilters(symbols?: string[]) { symbols = upperCaseSymbols(symbols) return [ { channel: 'trade', symbols } as const ] } *map(message: BitgetTradeMessage, localTimestamp: Date): IterableIterator<Trade> { for (let trade of message.data) { yield { type: 'trade', symbol: message.arg.instId, exchange: this._exchange, id: trade.tradeId, price: Number(trade.price), amount: Number(trade.size), side: trade.side === 'buy' ? 'buy' : 'sell', timestamp: new Date(Number(trade.ts)), localTimestamp: localTimestamp } } } } function mapPriceLevel(level: [string, string]) { return { price: Number(level[0]), amount: Number(level[1]) } } export class BitgetBookChangeMapper implements Mapper<'bitget' | 'bitget-futures', BookChange> { constructor(private readonly _exchange: Exchange) {} canHandle(message: BitgetOrderbookMessage) { return message.arg.channel === 'books15' && message.action === 'snapshot' } getFilters(symbols?: string[]) { symbols = upperCaseSymbols(symbols) return [ { channel: 'books15', symbols } as const ] } *map(message: BitgetOrderbookMessage, localTimestamp: Date): IterableIterator<BookChange> { for (let orderbookData of message.data) { yield { type: 'book_change', symbol: message.arg.instId, exchange: this._exchange, isSnapshot: message.action === 'snapshot', bids: orderbookData.bids.map(mapPriceLevel), asks: orderbookData.asks.map(mapPriceLevel), timestamp: new Date(Number(orderbookData.ts)), localTimestamp } } } } export class BitgetBookTickerMapper implements Mapper<'bitget' | 'bitget-futures', BookTicker> { constructor(private readonly _exchange: Exchange) {} canHandle(message: BitgetBBoMessage) { return message.arg.channel === 'books1' && message.action === 'snapshot' } getFilters(symbols?: string[]) { symbols = upperCaseSymbols(symbols) return [ { channel: `books1` as const, symbols } ] } *map(message: BitgetBBoMessage, localTimestamp: Date): IterableIterator<BookTicker> { for (const bboMessage of message.data) { const ticker: BookTicker = { type: 'book_ticker', symbol: message.arg.instId, exchange: this._exchange, askAmount: bboMessage.asks[0] ? Number(bboMessage.asks[0][1]) : undefined, askPrice: bboMessage.asks[0] ? Number(bboMessage.asks[0][0]) : undefined, bidPrice: bboMessage.bids[0] ? Number(bboMessage.bids[0][0]) : undefined, bidAmount: bboMessage.bids[0] ? Number(bboMessage.bids[0][1]) : undefined, timestamp: new Date(Number(bboMessage.ts)), localTimestamp: localTimestamp } yield ticker } } } export class BitgetDerivativeTickerMapper implements Mapper<'bitget-futures', DerivativeTicker> { private readonly pendingTickerInfoHelper = new PendingTickerInfoHelper() canHandle(message: BitgetTickerMessage) { return message.arg.channel === 'ticker' && message.action === 'snapshot' } getFilters(symbols?: string[]) { return [ { channel: 'ticker', symbols } as const ] } *map(message: BitgetTickerMessage, localTimestamp: Date): IterableIterator<DerivativeTicker> { for (const tickerMessage of message.data) { const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(tickerMessage.symbol, 'bitget-futures') pendingTickerInfo.updateIndexPrice(Number(tickerMessage.indexPrice)) pendingTickerInfo.updateMarkPrice(Number(tickerMessage.markPrice)) pendingTickerInfo.updateOpenInterest(Number(tickerMessage.holdingAmount)) pendingTickerInfo.updateLastPrice(Number(tickerMessage.lastPr)) pendingTickerInfo.updateTimestamp(new Date(Number(tickerMessage.ts))) if (tickerMessage.nextFundingTime !== '0') { pendingTickerInfo.updateFundingTimestamp(new Date(Number(tickerMessage.nextFundingTime))) pendingTickerInfo.updateFundingRate(Number(tickerMessage.fundingRate)) } if (pendingTickerInfo.hasChanged()) { yield pendingTickerInfo.getSnapshot(localTimestamp) } } } } type BitgetTradeMessage = { action: 'update' arg: { instType: 'SPOT'; channel: 'trade'; instId: 'OPUSDT' } data: [{ ts: '1730332800983'; price: '1.717'; size: '56.16'; side: 'buy'; tradeId: '1235670816495050754' }] ts: 1730332800989 } type BitgetOrderbookMessage = { action: 'snapshot' arg: { instType: 'SPOT'; channel: 'books15'; instId: 'GEMSUSDT' } data: [ { asks: [['0.22816', '155.25']] bids: [['0.22785', '73.41']] checksum: 0 ts: '1730963759993' } ] ts: 1730963759997 } type BitgetBBoMessage = { action: 'snapshot' arg: { instType: 'SPOT'; channel: 'books1'; instId: 'METISUSDT' } data: [{ asks: [['44.90', '0.6927']]; bids: [['44.82', '3.5344']]; checksum: 0; ts: '1730332859988' }] ts: 1730332859989 } type BitgetTickerMessage = { action: 'snapshot' arg: { instType: 'COIN-FUTURES'; channel: 'ticker'; instId: 'BTCUSD' } data: [ { instId: 'BTCUSD' lastPr: '72331.5' bidPr: '72331.5' askPr: '72331.8' bidSz: '7.296' askSz: '0.02' open24h: '72047.8' high24h: '72934.8' low24h: '71422.8' change24h: '-0.00561' fundingRate: '0.000116' nextFundingTime: string markPrice: string indexPrice: string holdingAmount: string baseVolume: '7543.376' quoteVolume: '544799876.924' openUtc: '72335.3' symbolType: '1' symbol: 'BTCUSD' deliveryPrice: '0' ts: '1730332823217' } ] ts: 1730332823220 }