UNPKG

tardis-machine

Version:

Locally runnable server with built-in data caching, providing both tick-level historical and consolidated real-time cryptocurrency market data via HTTP and WebSocket APIs

202 lines 7.15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.wait = exports.getComputables = exports.constructDataTypeFilter = exports.getNormalizers = void 0; const tardis_dev_1 = require("tardis-dev"); function* getNormalizers(dataTypes) { if (dataTypes.includes('trade') || dataTypes.some((dataType) => dataType.startsWith('trade_bar_'))) { yield tardis_dev_1.normalizeTrades; } if (dataTypes.includes('book_change') || dataTypes.some((dataType) => dataType.startsWith('book_snapshot_')) || dataTypes.some((dataType) => dataType.startsWith('quote'))) { yield tardis_dev_1.normalizeBookChanges; } if (dataTypes.includes('derivative_ticker')) { yield tardis_dev_1.normalizeDerivativeTickers; } if (dataTypes.includes('liquidation')) { yield tardis_dev_1.normalizeLiquidations; } if (dataTypes.includes('option_summary')) { yield tardis_dev_1.normalizeOptionsSummary; } if (dataTypes.includes('book_ticker')) { yield tardis_dev_1.normalizeBookTickers; } } exports.getNormalizers = getNormalizers; function getRequestedDataTypes(options) { return options.dataTypes.map((dataType) => { if (dataType.startsWith('trade_bar_')) { return 'trade_bar'; } if (dataType.startsWith('book_snapshot_')) { return 'book_snapshot'; } if (dataType.startsWith('quote')) { return 'book_snapshot'; } return dataType; }); } function constructDataTypeFilter(options) { const requestedDataTypesPerExchange = options.reduce((prev, current) => { if (prev[current.exchange] !== undefined) { prev[current.exchange] = [...prev[current.exchange], ...getRequestedDataTypes(current)]; } else { prev[current.exchange] = getRequestedDataTypes(current); } return prev; }, {}); const returnDisconnectMessages = options.some((o) => o.withDisconnectMessages); return (message) => { if (message.type === 'disconnect' && returnDisconnectMessages) { return true; } return requestedDataTypesPerExchange[message.exchange].includes(message.type); }; } exports.constructDataTypeFilter = constructDataTypeFilter; const tradeBarSuffixToKindMap = { ticks: { kind: 'tick', multiplier: 1 }, ms: { kind: 'time', multiplier: 1 }, s: { kind: 'time', multiplier: 1000 }, m: { kind: 'time', multiplier: 60 * 1000 }, vol: { kind: 'volume', multiplier: 1 } }; const bookSnapshotsToIntervalMultiplierMap = { ms: { multiplier: 1 }, s: { multiplier: 1000 }, m: { multiplier: 60 * 1000 } }; const getKeys = (o) => Object.keys(o); function getComputables(dataTypes) { const computables = []; for (const dataType of dataTypes) { if (dataType.startsWith('trade_bar')) { computables.push(parseAsTradeBarComputable(dataType)); } if (dataType.startsWith('book_snapshot')) { computables.push(parseAsBookSnapshotComputable(dataType)); } if (dataType.startsWith('quote')) { computables.push(parseAsQuoteComputable(dataType)); } } return computables; } exports.getComputables = getComputables; function parseAsTradeBarComputable(dataType) { for (const suffix of getKeys(tradeBarSuffixToKindMap)) { if (dataType.endsWith(suffix) === false) { continue; } const intervalString = dataType.replace('trade_bar_', '').replace(suffix, ''); const interval = Number(intervalString); if (Number.isNaN(interval)) { throw new Error(`invalid interval: ${intervalString}, data type: ${dataType}`); } return (0, tardis_dev_1.computeTradeBars)({ interval: tradeBarSuffixToKindMap[suffix].multiplier * interval, kind: tradeBarSuffixToKindMap[suffix].kind, name: dataType }); } throw new Error(`invalid data type: ${dataType}`); } function parseAsBookSnapshotComputable(dataType) { for (const suffix of getKeys(bookSnapshotsToIntervalMultiplierMap)) { if (dataType.endsWith(suffix) === false) { continue; } const parts = dataType.split('_'); const depthString = parts[2]; const depth = Number(parts[2]); if (Number.isNaN(depth)) { throw new Error(`invalid depth: ${depthString}, data type: ${dataType}`); } const intervalString = parts[parts.length - 1].replace(suffix, ''); const interval = Number(intervalString); if (Number.isNaN(interval)) { throw new Error(`invalid interval: ${intervalString}, data type: ${dataType}`); } const isGrouped = parts.length === 5; let grouping; if (isGrouped) { const groupingString = parts[3].replace('grouped', ''); grouping = Number(groupingString); if (Number.isNaN(grouping)) { throw new Error(`invalid interval: ${groupingString}, data type: ${dataType}`); } } return (0, tardis_dev_1.computeBookSnapshots)({ interval: bookSnapshotsToIntervalMultiplierMap[suffix].multiplier * interval, grouping, depth, name: dataType, removeCrossedLevels: true }); } throw new Error(`invalid data type: ${dataType}`); } function parseAsQuoteComputable(dataType) { if (dataType === 'quote') { return (0, tardis_dev_1.computeBookSnapshots)({ interval: 0, depth: 1, name: dataType, removeCrossedLevels: true }); } for (const suffix of getKeys(bookSnapshotsToIntervalMultiplierMap)) { if (dataType.endsWith(suffix) === false) { continue; } const intervalString = dataType.replace('quote_', '').replace(suffix, ''); const interval = Number(intervalString); if (Number.isNaN(interval)) { throw new Error(`invalid interval: ${intervalString}, data type: ${dataType}`); } return (0, tardis_dev_1.computeBookSnapshots)({ interval: bookSnapshotsToIntervalMultiplierMap[suffix].multiplier * interval, depth: 1, name: dataType, removeCrossedLevels: true }); } throw new Error(`invalid data type: ${dataType}`); } const wait = (delayMS) => new Promise((resolve) => setTimeout(resolve, delayMS)); exports.wait = wait; const oldToISOString = Date.prototype.toISOString; // if Date provides microseconds add those to ISO date Date.prototype.toISOString = function () { if (this.μs !== undefined) { const isoString = oldToISOString.apply(this); return isoString.slice(0, isoString.length - 1) + this.μs.toString().padStart(3, '0') + 'Z'; } return oldToISOString.apply(this); }; //# sourceMappingURL=helpers.js.map