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
JavaScript
;
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