tardis-dev
Version:
Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js
274 lines • 10.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.deribitBookTickerMapper = exports.deribitLiquidationsMapper = exports.DeribitOptionSummaryMapper = exports.DeribitDerivativeTickerMapper = exports.deribitBookChangeMapper = exports.deribitTradesMapper = void 0;
const handy_1 = require("../handy");
const mapper_1 = require("./mapper");
// 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;
}
exports.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 };
};
exports.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
};
}
};
class DeribitDerivativeTickerMapper {
constructor() {
this.pendingTickerInfoHelper = new mapper_1.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);
}
}
}
exports.DeribitDerivativeTickerMapper = DeribitDerivativeTickerMapper;
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: (0, handy_1.asNumberIfValid)(optionInfo.best_bid_price),
bestBidAmount: (0, handy_1.asNumberIfValid)(optionInfo.best_bid_amount),
bestBidIV: (0, handy_1.asNumberIfValid)(optionInfo.bid_iv),
bestAskPrice: (0, handy_1.asNumberIfValid)(optionInfo.best_ask_price),
bestAskAmount: (0, handy_1.asNumberIfValid)(optionInfo.best_ask_amount),
bestAskIV: (0, handy_1.asNumberIfValid)(optionInfo.ask_iv),
lastPrice: (0, handy_1.asNumberIfValid)(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;
}
}
exports.DeribitOptionSummaryMapper = DeribitOptionSummaryMapper;
exports.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
};
}
}
}
};
exports.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: (0, handy_1.asNumberIfValid)(deribitTicker.best_ask_amount),
askPrice: (0, handy_1.asNumberIfValid)(deribitTicker.best_ask_price),
bidPrice: (0, handy_1.asNumberIfValid)(deribitTicker.best_bid_price),
bidAmount: (0, handy_1.asNumberIfValid)(deribitTicker.best_bid_amount),
timestamp: new Date(deribitTicker.timestamp),
localTimestamp: localTimestamp
};
yield ticker;
}
};
//# sourceMappingURL=deribit.js.map