UNPKG

tardis-dev

Version:

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

181 lines 6.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BinanceOptionSummaryMapper = exports.BinanceOptionsBookChangeMapper = exports.BinanceOptionsTradesMapper = void 0; const handy_1 = require("../handy"); // https://github.com/binance-exchange/binance-official-api-docs/blob/master/web-socket-streams.md class BinanceOptionsTradesMapper { constructor() { this._lastTradeId = new Map(); } canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.endsWith('@TRADE'); } getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); return [ { channel: 'TRADE', symbols } ]; } *map(binanceTradeResponse, localTimestamp) { const symbol = binanceTradeResponse.data.s; for (const optionsTrade of binanceTradeResponse.data.t) { // binance options does not only return real-time trade as it happens but just snapshot of last 'x' trades always // so we need to decide which are real-time trades and which are stale/already processed const timestamp = new Date(optionsTrade.T); const tradeIdNumeric = Number(optionsTrade.t); const lastProcessedTradeId = this._lastTradeId.get(symbol); const isAlreadyProcessed = lastProcessedTradeId !== undefined && lastProcessedTradeId >= tradeIdNumeric; const isStaleTrade = localTimestamp.valueOf() - timestamp.valueOf() > 10000; if (isAlreadyProcessed || isStaleTrade) { continue; } this._lastTradeId.set(symbol, Number(optionsTrade.t)); const trade = { type: 'trade', symbol, exchange: 'binance-options', id: optionsTrade.t, price: Number(optionsTrade.p), amount: Number(optionsTrade.q), side: optionsTrade.s === '-1' ? 'sell' : 'buy', timestamp, localTimestamp: localTimestamp }; yield trade; } } } exports.BinanceOptionsTradesMapper = BinanceOptionsTradesMapper; class BinanceOptionsBookChangeMapper { canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.endsWith('@DEPTH100'); } getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); return [ { channel: 'DEPTH100', symbols } ]; } *map(message, localTimestamp) { const bookChange = { type: 'book_change', symbol: message.data.s, exchange: 'binance-options', isSnapshot: true, bids: message.data.b.map(this.mapBookLevel), asks: message.data.a.map(this.mapBookLevel), timestamp: new Date(message.data.E), localTimestamp }; yield bookChange; } mapBookLevel(level) { const price = Number(level[0]); const amount = Number(level[1]); return { price, amount }; } } exports.BinanceOptionsBookChangeMapper = BinanceOptionsBookChangeMapper; class BinanceOptionSummaryMapper { constructor() { this._indexPrices = new Map(); } canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.endsWith('@TICKER') || message.stream.endsWith('@INDEX'); } getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); const indexes = symbols !== undefined ? symbols.map((s) => { const symbolParts = s.split('-'); return `${symbolParts[0]}USDT`; }) : undefined; return [ { channel: 'TICKER', symbols }, { channel: 'INDEX', symbols: indexes } ]; } *map(message, localTimestamp) { if (message.stream.endsWith('@INDEX')) { const lastIndexPrice = Number(message.data.p); if (lastIndexPrice > 0) { this._indexPrices.set(message.data.s, lastIndexPrice); } return; } const optionInfo = message.data; const [base, expiryPart, strikePrice, optionType] = optionInfo.s.split('-'); const expirationDate = new Date(`20${expiryPart.slice(0, 2)}-${expiryPart.slice(2, 4)}-${expiryPart.slice(4, 6)}Z`); expirationDate.setUTCHours(8); const isPut = optionType === 'P'; const underlyingIndex = `${base}USDT`; let bestBidPrice = (0, handy_1.asNumberIfValid)(optionInfo.bo); if (bestBidPrice === 0) { bestBidPrice = undefined; } let bestAskPrice = (0, handy_1.asNumberIfValid)(optionInfo.ao); if (bestAskPrice === 0) { bestAskPrice = undefined; } let bestBidIV = bestBidPrice !== undefined ? (0, handy_1.asNumberIfValid)(optionInfo.b) : undefined; if (bestBidIV === -1) { bestBidIV = undefined; } let bestAskIV = bestAskPrice !== undefined ? (0, handy_1.asNumberIfValid)(optionInfo.a) : undefined; if (bestAskIV === -1) { bestAskIV = undefined; } const optionSummary = { type: 'option_summary', symbol: optionInfo.s, exchange: 'binance-options', optionType: isPut ? 'put' : 'call', strikePrice: Number(strikePrice), expirationDate, bestBidPrice, bestBidAmount: undefined, bestBidIV, bestAskPrice, bestAskAmount: undefined, bestAskIV, lastPrice: (0, handy_1.asNumberIfValid)(optionInfo.c), openInterest: undefined, markPrice: (0, handy_1.asNumberIfValid)(optionInfo.mp), markIV: undefined, delta: (0, handy_1.asNumberIfValid)(optionInfo.d), gamma: (0, handy_1.asNumberIfValid)(optionInfo.g), vega: (0, handy_1.asNumberIfValid)(optionInfo.v), theta: (0, handy_1.asNumberIfValid)(optionInfo.t), rho: undefined, underlyingPrice: this._indexPrices.get(underlyingIndex), underlyingIndex, timestamp: new Date(optionInfo.E), localTimestamp: localTimestamp }; yield optionSummary; } } exports.BinanceOptionSummaryMapper = BinanceOptionSummaryMapper; //# sourceMappingURL=binanceoptions.js.map