UNPKG

tardis-dev

Version:

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

267 lines 9.98 kB
import { asNonZeroNumberOrUndefined } from "../handy.js"; import { PendingTickerInfoHelper } from "./mapper.js"; // https://docs.deribit.com/v2/#subscriptions function deribitCasing(symbols) { if (symbols !== undefined) { return symbols.map((symbol) => { if (symbol.endsWith('-C') || symbol.endsWith('-P')) { const parts = symbol.split('-'); if (parts[2] !== undefined && parts[2].toUpperCase().includes('D')) { parts[2] = parts[2].replace('D', 'd'); return parts.join('-'); } else { return symbol.toUpperCase(); } } else { return symbol.toUpperCase(); } }); } return; } export const deribitTradesMapper = { canHandle(message) { const channel = message.params !== undefined ? message.params.channel : undefined; if (channel === undefined) { return false; } return channel.startsWith('trades'); }, getFilters(symbols) { symbols = deribitCasing(symbols); return [ { channel: 'trades', symbols } ]; }, *map(message, localTimestamp) { for (const deribitTrade of message.params.data) { yield { type: 'trade', symbol: deribitTrade.instrument_name.toUpperCase(), exchange: 'deribit', id: deribitTrade.trade_id, price: deribitTrade.price, amount: deribitTrade.amount, side: deribitTrade.direction, timestamp: new Date(deribitTrade.timestamp), localTimestamp: localTimestamp }; } } }; const mapBookLevel = (level) => { const price = level[1]; const amount = level[0] === 'delete' ? 0 : level[2]; return { price, amount }; }; export const deribitBookChangeMapper = { canHandle(message) { const channel = message.params && message.params.channel; if (channel === undefined) { return false; } return channel.startsWith('book'); }, getFilters(symbols) { symbols = deribitCasing(symbols); return [ { channel: 'book', symbols } ]; }, *map(message, localTimestamp) { const deribitBookChange = message.params.data; // snapshots do not have prev_change_id set const isSnapshot = (deribitBookChange.type !== undefined && deribitBookChange.type === 'snapshot') || deribitBookChange.prev_change_id === undefined || deribitBookChange.prev_change_id === 0; yield { type: 'book_change', symbol: deribitBookChange.instrument_name.toUpperCase(), exchange: 'deribit', isSnapshot, bids: deribitBookChange.bids.map(mapBookLevel), asks: deribitBookChange.asks.map(mapBookLevel), timestamp: new Date(deribitBookChange.timestamp), localTimestamp: localTimestamp }; } }; export class DeribitDerivativeTickerMapper { pendingTickerInfoHelper = new PendingTickerInfoHelper(); canHandle(message) { const channel = message.params && message.params.channel; if (channel === undefined) { return false; } return channel.startsWith('ticker') && (message.params.data.greeks === undefined || message.params.data.combo_state === 'active'); } getFilters(symbols) { symbols = deribitCasing(symbols); return [ { channel: 'ticker', symbols } ]; } *map(message, localTimestamp) { const deribitTicker = message.params.data; const pendingTickerInfo = this.pendingTickerInfoHelper.getPendingTickerInfo(deribitTicker.instrument_name, 'deribit'); pendingTickerInfo.updateFundingRate(deribitTicker.current_funding); pendingTickerInfo.updateIndexPrice(deribitTicker.index_price); pendingTickerInfo.updateMarkPrice(deribitTicker.mark_price); pendingTickerInfo.updateOpenInterest(deribitTicker.open_interest); pendingTickerInfo.updateLastPrice(deribitTicker.last_price); pendingTickerInfo.updateTimestamp(new Date(deribitTicker.timestamp)); if (pendingTickerInfo.hasChanged()) { yield pendingTickerInfo.getSnapshot(localTimestamp); } } } export class DeribitOptionSummaryMapper { getFilters(symbols) { symbols = deribitCasing(symbols); return [ { channel: 'ticker', symbols } ]; } canHandle(message) { const channel = message.params && message.params.channel; if (channel === undefined) { return false; } return (channel.startsWith('ticker') && (message.params.data.instrument_name.endsWith('-P') || message.params.data.instrument_name.endsWith('-C'))); } *map(message, localTimestamp) { //MATIC_USDC-9MAR24-1d02-C const optionInfo = message.params.data; //e.g., BTC-8JUN20-8750-P const symbolParts = optionInfo.instrument_name.split('-'); const isPut = symbolParts[3] === 'P'; let strikePriceString = symbolParts[2]; if (strikePriceString.includes('d')) { strikePriceString = strikePriceString.replace('d', '.'); } const strikePrice = Number(strikePriceString); const expirationDate = new Date(symbolParts[1] + 'Z'); expirationDate.setUTCHours(8); const optionSummary = { type: 'option_summary', symbol: optionInfo.instrument_name.toUpperCase(), exchange: 'deribit', optionType: isPut ? 'put' : 'call', strikePrice, expirationDate, bestBidPrice: asNonZeroNumberOrUndefined(optionInfo.best_bid_price), bestBidAmount: asNonZeroNumberOrUndefined(optionInfo.best_bid_amount), bestBidIV: asNonZeroNumberOrUndefined(optionInfo.bid_iv), bestAskPrice: asNonZeroNumberOrUndefined(optionInfo.best_ask_price), bestAskAmount: asNonZeroNumberOrUndefined(optionInfo.best_ask_amount), bestAskIV: asNonZeroNumberOrUndefined(optionInfo.ask_iv), lastPrice: asNonZeroNumberOrUndefined(optionInfo.last_price), openInterest: optionInfo.open_interest, markPrice: optionInfo.mark_price, markIV: optionInfo.mark_iv, delta: optionInfo.greeks.delta, gamma: optionInfo.greeks.gamma, vega: optionInfo.greeks.vega, theta: optionInfo.greeks.theta, rho: optionInfo.greeks.rho, underlyingPrice: optionInfo.underlying_price, underlyingIndex: optionInfo.underlying_index, timestamp: new Date(optionInfo.timestamp), localTimestamp: localTimestamp }; yield optionSummary; } } export const deribitLiquidationsMapper = { canHandle(message) { const channel = message.params !== undefined ? message.params.channel : undefined; if (channel === undefined) { return false; } return channel.startsWith('trades'); }, getFilters(symbols) { symbols = deribitCasing(symbols); return [ { channel: 'trades', symbols } ]; }, *map(message, localTimestamp) { for (const deribitTrade of message.params.data) { if (deribitTrade.liquidation !== undefined) { let side; // "T" when liquidity taker side was under liquidation if (deribitTrade.liquidation === 'T') { side = deribitTrade.direction; } else { // "M" when maker (passive) side of trade was under liquidation side = deribitTrade.direction === 'buy' ? 'sell' : 'buy'; } yield { type: 'liquidation', symbol: deribitTrade.instrument_name.toUpperCase(), exchange: 'deribit', id: deribitTrade.trade_id, price: deribitTrade.price, amount: deribitTrade.amount, side, timestamp: new Date(deribitTrade.timestamp), localTimestamp: localTimestamp }; } } } }; export const deribitBookTickerMapper = { canHandle(message) { const channel = message.params !== undefined ? message.params.channel : undefined; if (channel === undefined) { return false; } return channel.startsWith('ticker'); }, getFilters(symbols) { symbols = deribitCasing(symbols); return [ { channel: 'ticker', symbols } ]; }, *map(message, localTimestamp) { const deribitTicker = message.params.data; const ticker = { type: 'book_ticker', symbol: deribitTicker.instrument_name.toUpperCase(), exchange: 'deribit', askAmount: asNonZeroNumberOrUndefined(deribitTicker.best_ask_amount), askPrice: asNonZeroNumberOrUndefined(deribitTicker.best_ask_price), bidPrice: asNonZeroNumberOrUndefined(deribitTicker.best_bid_price), bidAmount: asNonZeroNumberOrUndefined(deribitTicker.best_bid_amount), timestamp: new Date(deribitTicker.timestamp), localTimestamp: localTimestamp }; yield ticker; } }; //# sourceMappingURL=deribit.js.map