UNPKG

tardis-dev

Version:

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

420 lines 15.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BinanceEuropeanOptionSummaryMapperV2 = exports.BinanceEuropeanOptionSummaryMapper = exports.BinanceEuropeanOptionsBookTickerMapper = exports.BinanceEuropeanOptionsBookChangeMapperV2 = exports.BinanceEuropeanOptionsBookChangeMapper = exports.BinanceEuropeanOptionsTradesMapperV2 = exports.BinanceEuropeanOptionsTradesMapper = void 0; const handy_1 = require("../handy"); // https://binance-docs.github.io/apidocs/voptions/en/#websocket-market-streams class BinanceEuropeanOptionsTradesMapper { 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 trade = { type: 'trade', symbol: binanceTradeResponse.data.s, exchange: 'binance-european-options', id: binanceTradeResponse.data.t, price: Number(binanceTradeResponse.data.p), amount: Number(binanceTradeResponse.data.q), side: binanceTradeResponse.data.S === '-1' ? 'sell' : 'buy', timestamp: new Date(binanceTradeResponse.data.T), localTimestamp: localTimestamp }; yield trade; } } exports.BinanceEuropeanOptionsTradesMapper = BinanceEuropeanOptionsTradesMapper; class BinanceEuropeanOptionsTradesMapperV2 { canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.endsWith('@optionTrade'); } getFilters(symbols) { symbols = (0, handy_1.lowerCaseSymbols)(symbols); return [ { channel: 'optionTrade', symbols } ]; } *map(binanceTradeResponse, localTimestamp) { const trade = { type: 'trade', symbol: binanceTradeResponse.data.s, exchange: 'binance-european-options', id: String(binanceTradeResponse.data.t), price: Number(binanceTradeResponse.data.p), amount: Number(binanceTradeResponse.data.q), side: binanceTradeResponse.data.m ? 'sell' : 'buy', timestamp: new Date(binanceTradeResponse.data.T), localTimestamp: localTimestamp }; yield trade; } } exports.BinanceEuropeanOptionsTradesMapperV2 = BinanceEuropeanOptionsTradesMapperV2; class BinanceEuropeanOptionsBookChangeMapper { canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.includes('@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-european-options', isSnapshot: true, bids: message.data.b.map(this.mapBookLevel), asks: message.data.a.map(this.mapBookLevel), timestamp: message.data.E !== undefined ? new Date(message.data.E) : new Date(message.data.T), localTimestamp }; yield bookChange; } mapBookLevel(level) { const price = Number(level[0]); const amount = Number(level[1]); return { price, amount }; } } exports.BinanceEuropeanOptionsBookChangeMapper = BinanceEuropeanOptionsBookChangeMapper; class BinanceEuropeanOptionsBookChangeMapperV2 { canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.includes('@depth20'); } getFilters(symbols) { symbols = (0, handy_1.lowerCaseSymbols)(symbols); return [ { channel: 'depth20', symbols } ]; } *map(message, localTimestamp) { const bookChange = { type: 'book_change', symbol: message.data.s, exchange: 'binance-european-options', isSnapshot: true, bids: message.data.b.map(this.mapBookLevel), asks: message.data.a.map(this.mapBookLevel), timestamp: new Date(message.data.T), localTimestamp }; yield bookChange; } mapBookLevel(level) { const price = Number(level[0]); const amount = Number(level[1]); return { price, amount }; } } exports.BinanceEuropeanOptionsBookChangeMapperV2 = BinanceEuropeanOptionsBookChangeMapperV2; class BinanceEuropeanOptionsBookTickerMapper { canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.endsWith('@bookTicker'); } getFilters(symbols) { symbols = (0, handy_1.lowerCaseSymbols)(symbols); return [ { channel: 'bookTicker', symbols } ]; } *map(message, localTimestamp) { const bestBidPrice = Number(message.data.b); const bestBidAmount = Number(message.data.B); const bestAskPrice = Number(message.data.a); const bestAskAmount = Number(message.data.A); const bookTicker = { type: 'book_ticker', symbol: message.data.s, exchange: 'binance-european-options', bidPrice: bestBidPrice > 0 ? bestBidPrice : undefined, bidAmount: bestBidAmount > 0 ? bestBidAmount : undefined, askPrice: bestAskPrice > 0 ? bestAskPrice : undefined, askAmount: bestAskAmount > 0 ? bestAskAmount : undefined, timestamp: new Date(message.data.T), localTimestamp }; yield bookTicker; } } exports.BinanceEuropeanOptionsBookTickerMapper = BinanceEuropeanOptionsBookTickerMapper; class BinanceEuropeanOptionSummaryMapper { _indexPrices = new Map(); _openInterests = new Map(); canHandle(message) { if (message.stream === undefined) { return false; } return message.stream.endsWith('@ticker') || message.stream.endsWith('@index') || message.stream.includes('@openInterest'); } getFilters(symbols) { symbols = (0, handy_1.upperCaseSymbols)(symbols); const indexes = symbols !== undefined ? symbols.map((s) => { const symbolParts = s.split('-'); return `${symbolParts[0]}USDT`; }) : undefined; const underlyings = symbols !== undefined ? symbols.map((s) => { const symbolParts = s.split('-'); return `${symbolParts[0]}`; }) : undefined; return [ { channel: 'ticker', symbols }, { channel: 'index', symbols: indexes }, { channel: 'openInterest', symbols: underlyings } ]; } *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; } if (message.stream.includes('@openInterest')) { for (let data of message.data) { const openInterest = Number(data.o); if (openInterest >= 0) { this._openInterests.set(data.s, openInterest); } } 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 bestBidAmount = (0, handy_1.asNumberIfValid)(optionInfo.bq); if (bestBidAmount === 0) { bestBidAmount = undefined; } let bestAskPrice = (0, handy_1.asNumberIfValid)(optionInfo.ao); if (bestAskPrice === 0) { bestAskPrice = undefined; } let bestAskAmount = (0, handy_1.asNumberIfValid)(optionInfo.aq); if (bestAskAmount === 0) { bestAskAmount = 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-european-options', optionType: isPut ? 'put' : 'call', strikePrice: Number(strikePrice), expirationDate, bestBidPrice, bestBidAmount, bestBidIV, bestAskPrice, bestAskAmount, bestAskIV, lastPrice: (0, handy_1.asNumberIfValid)(optionInfo.c), openInterest: this._openInterests.get(optionInfo.s), 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.BinanceEuropeanOptionSummaryMapper = BinanceEuropeanOptionSummaryMapper; class BinanceEuropeanOptionSummaryMapperV2 { _lastPrices = new Map(); _openInterests = new Map(); canHandle(message) { if (message.stream === undefined) { return false; } return (message.stream.endsWith('@optionMarkPrice') || message.stream.endsWith('@optionTicker') || message.stream.includes('@optionOpenInterest')); } getFilters(symbols) { symbols = (0, handy_1.lowerCaseSymbols)(symbols); const underlyings = symbols !== undefined ? symbols.map((s) => { const symbolParts = s.split('-'); return `${symbolParts[0]}usdt`; }) : undefined; return [ { channel: 'optionMarkPrice', symbols: underlyings }, { channel: 'optionTicker', symbols }, { channel: 'optionOpenInterest', symbols: underlyings } ]; } *map(message, localTimestamp) { // Handle optionTicker messages to track last prices if (message.stream.endsWith('@optionTicker')) { const tickerData = message.data; const lastPrice = Number(tickerData.c); if (lastPrice > 0) { this._lastPrices.set(tickerData.s, lastPrice); } return; } // Handle optionOpenInterest messages to track open interest if (message.stream.includes('@optionOpenInterest')) { const openInterestArray = message.data; for (let oi of openInterestArray) { const openInterest = Number(oi.o); if (openInterest >= 0) { this._openInterests.set(oi.s, openInterest); } } return; } // optionMarkPrice contains all data needed: greeks, IV, best bid/ask, mark price, and index price const markPriceArray = message.data; for (let markData of markPriceArray) { const [base, expiryPart, strikePrice, optionType] = markData.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)(markData.bo); if (bestBidPrice === 0) { bestBidPrice = undefined; } let bestBidAmount = (0, handy_1.asNumberIfValid)(markData.bq); if (bestBidAmount === 0) { bestBidAmount = undefined; } let bestAskPrice = (0, handy_1.asNumberIfValid)(markData.ao); if (bestAskPrice === 0) { bestAskPrice = undefined; } let bestAskAmount = (0, handy_1.asNumberIfValid)(markData.aq); if (bestAskAmount === 0) { bestAskAmount = undefined; } let bestBidIV = bestBidPrice !== undefined ? (0, handy_1.asNumberIfValid)(markData.b) : undefined; if (bestBidIV === -1) { bestBidIV = undefined; } let bestAskIV = bestAskPrice !== undefined ? (0, handy_1.asNumberIfValid)(markData.a) : undefined; if (bestAskIV === -1) { bestAskIV = undefined; } const markPrice = (0, handy_1.asNumberIfValid)(markData.mp); const markIV = (0, handy_1.asNumberIfValid)(markData.vo); const delta = (0, handy_1.asNumberIfValid)(markData.d); const gamma = (0, handy_1.asNumberIfValid)(markData.g); const vega = (0, handy_1.asNumberIfValid)(markData.v); const theta = (0, handy_1.asNumberIfValid)(markData.t); const underlyingPrice = (0, handy_1.asNumberIfValid)(markData.i); // Index price is included in mark price data const optionSummary = { type: 'option_summary', symbol: markData.s, exchange: 'binance-european-options', optionType: isPut ? 'put' : 'call', strikePrice: Number(strikePrice), expirationDate, bestBidPrice, bestBidAmount, bestBidIV, bestAskPrice, bestAskAmount, bestAskIV, lastPrice: this._lastPrices.get(markData.s), openInterest: this._openInterests.get(markData.s), markPrice, markIV, delta, gamma, vega, theta, rho: undefined, underlyingPrice, underlyingIndex, timestamp: new Date(markData.E), localTimestamp: localTimestamp }; yield optionSummary; } } } exports.BinanceEuropeanOptionSummaryMapperV2 = BinanceEuropeanOptionSummaryMapperV2; //# sourceMappingURL=binanceeuropeanoptions.js.map