@hackape/tardis-dev
Version:
Convenient access to tick-level historical and real-time cryptocurrency market data via Node.js
111 lines • 5.36 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.downloadDatasets = void 0;
const p_map_1 = __importDefault(require("p-map"));
const debug_1 = require("./debug");
const handy_1 = require("./handy");
const options_1 = require("./options");
const CONCURRENCY_LIMIT = 20;
const MILLISECONDS_IN_SINGLE_DAY = 24 * 60 * 60 * 1000;
const DEFAULT_DOWNLOAD_DIR = './datasets';
const options = options_1.getOptions();
async function downloadDatasets(downloadDatasetsOptions) {
const { exchange, dataTypes, from, to, symbols } = downloadDatasetsOptions;
const apiKey = downloadDatasetsOptions.apiKey !== undefined ? downloadDatasetsOptions.apiKey : options.apiKey;
const downloadDir = downloadDatasetsOptions.downloadDir !== undefined ? downloadDatasetsOptions.downloadDir : DEFAULT_DOWNLOAD_DIR;
const format = downloadDatasetsOptions.format !== undefined ? downloadDatasetsOptions.format : 'csv';
const getFilename = downloadDatasetsOptions.getFilename !== undefined ? downloadDatasetsOptions.getFilename : getFilenameDefault;
// in case someone provided 'api/exchange' symbol, transform it to symbol that is accepted by datasets API
const datasetsSymbols = symbols.map((s) => s.replace(/\/|:/g, '-').toUpperCase());
for (const symbol of datasetsSymbols) {
for (const dataType of dataTypes) {
const { daysCountToFetch, startDate } = getDownloadDateRange(downloadDatasetsOptions);
const startTimestamp = new Date().valueOf();
debug_1.debug('dataset download started for %s %s %s from %s to %s', exchange, dataType, symbol, from, to);
if (daysCountToFetch > 1) {
// start with downloading last day of the range, validates is API key has access to the end range of requested data
await handy_1.download(getDownloadOptions({
exchange,
symbol,
apiKey,
downloadDir,
dataType,
format,
getFilename,
date: handy_1.addDays(startDate, daysCountToFetch - 1)
}));
}
// then download the first day of the range, validates is API key has access to the start range of requested data
await handy_1.download(getDownloadOptions({
exchange,
symbol,
apiKey,
downloadDir,
dataType,
format,
getFilename,
date: startDate
}));
// download the rest concurrently up to the CONCURRENCY_LIMIT
await p_map_1.default(handy_1.sequence(daysCountToFetch - 1, 1), // this will produce Iterable sequence from 1 to daysCountToFetch - 1 (as we already downloaded data for the first and last day)
(offset) => handy_1.download(getDownloadOptions({
exchange,
symbol,
apiKey,
downloadDir,
dataType,
format,
getFilename,
date: handy_1.addDays(startDate, offset)
})), { concurrency: CONCURRENCY_LIMIT });
const elapsedSeconds = (new Date().valueOf() - startTimestamp) / 1000;
debug_1.debug('dataset download finished for %s %s %s from %s to %s, time: %s seconds', exchange, dataType, symbol, from, to, elapsedSeconds);
}
}
}
exports.downloadDatasets = downloadDatasets;
function getDownloadOptions({ apiKey, exchange, dataType, date, symbol, format, downloadDir, getFilename }) {
const year = date.getUTCFullYear();
const month = handy_1.doubleDigit(date.getUTCMonth() + 1);
const day = handy_1.doubleDigit(date.getUTCDate());
const url = `${options.datasetsEndpoint}/${exchange}/${dataType}/${year}/${month}/${day}/${symbol}.${format}.gz`;
const filename = getFilename({
dataType,
date,
exchange,
format,
symbol
});
const downloadPath = `${downloadDir}/${filename}`;
return {
url,
downloadPath,
userAgent: options._userAgent,
apiKey
};
}
function getFilenameDefault({ exchange, dataType, format, date, symbol }) {
return `${exchange}_${dataType}_${date.toISOString().split('T')[0]}_${symbol}.${format}.gz`;
}
function getDownloadDateRange({ from, to }) {
if (!from || isNaN(Date.parse(from))) {
throw new Error(`Invalid "from" argument: ${from}. Please provide valid date string.`);
}
if (!to || isNaN(Date.parse(to))) {
throw new Error(`Invalid "to" argument: ${to}. Please provide valid date string.`);
}
const toDate = handy_1.parseAsUTCDate(to);
const fromDate = handy_1.parseAsUTCDate(from);
const daysCountToFetch = Math.floor((toDate.getTime() - fromDate.getTime()) / MILLISECONDS_IN_SINGLE_DAY);
if (daysCountToFetch < 1) {
throw new Error(`Invalid "to" and "from" arguments combination. Please provide "to" day that is later than "from" day.`);
}
return {
startDate: fromDate,
daysCountToFetch
};
}
//# sourceMappingURL=downloaddatasets.js.map
;