taapi-cache
Version:
TAAPI.IO Cache Package. A convenient way to fetch candles, store them and reuse them.
152 lines (115 loc) • 5.16 kB
JavaScript
const moment = require('moment');
const mongodb = require("mongodb");
const database = require("../utilities/Database");
const config = require("../config/config");
const chalk = require("chalk");
const nodeSchedule = require("node-schedule");
const taapi = require("taapi");
const {
Sema
} = require('async-sema');
class Scheduler {
constructor() {
this.exchangeData = taapi.exchangeData();
this.exchangeDataLocks = {};
}
async sleep(time) {
return await new Promise(resolve => setTimeout(resolve, time));
}
startMonitor() {
if (config.dataProviders) {
// Set up CCXT schedulers
for (let exchangeId in config.dataProviders.ccxt) {
let dataProvider = config.dataProviders.ccxt[exchangeId];
for (let interval in dataProvider.schedulers) {
let schedule = config.dataProviders.ccxt[exchangeId].schedulers[interval];
if (schedule.enabled) {
this.exchangeDataLocks[exchangeId] = new Sema(1);
nodeSchedule.scheduleJob(schedule.cron, async date => {
const cacheTickers = await database.getCacheTickers("ccxt", exchangeId, null, interval);
for (let cacheTickerKey in cacheTickers) {
const cacheTicker = cacheTickers[cacheTickerKey];
this.fetchAndCacheCandles(exchangeId, "ccxt", null, cacheTicker);
await this.sleep(schedule.rateLimit);
}
});
}
}
} // Set up AlphaVantage schedulers
for (let interval in config.dataProviders.alphaVantage.schedulers) {
let dataProvider = config.dataProviders.alphaVantage;
let schedule = dataProvider.schedulers[interval];
if (schedule.enabled) {
this.exchangeDataLocks["alphavantage"] = new Sema(1);
nodeSchedule.scheduleJob(schedule.cron, async date => {
const cacheTickers = await database.getCacheTickers("alphavantage", null, null, interval);
for (let cacheTickerKey in cacheTickers) {
const cacheTicker = cacheTickers[cacheTickerKey];
this.fetchAndCacheCandles("alphavantage", "alphavantage", config.dataProviders.alphaVantage.secret, cacheTicker);
await this.sleep(dataProvider.rateLimit);
}
});
}
} // Set up FinnHub schedulers
for (let interval in config.dataProviders.finnHub.schedulers) {
let dataProvider = config.dataProviders.finnHub;
let schedule = dataProvider.schedulers[interval];
if (schedule.enabled) {
this.exchangeDataLocks["finnhub"] = new Sema(1);
nodeSchedule.scheduleJob(schedule.cron, async date => {
const cacheTickers = await database.getCacheTickers("finnhub", null, null, interval);
for (let cacheTickerKey in cacheTickers) {
const cacheTicker = cacheTickers[cacheTickerKey];
this.fetchAndCacheCandles("finnhub", "finnhub", config.dataProviders.finnHub.secret, cacheTicker);
await this.sleep(dataProvider.rateLimit);
}
});
}
}
}
}
async fetchAndCacheCandles(exchangeDataLockName, providerName, providerSecret, cacheTicker) {
const self = this;
await this.exchangeDataLocks[exchangeDataLockName].acquire();
let execTime = new Date().getTime();
if (config.server.debugMode) {
console.log(`Exec ${execTime}: ${providerName}:${cacheTicker.source} - ${cacheTicker.symbol}:${cacheTicker.interval}`);
} // Get data provider secret
this.exchangeData.setDataProvider(providerName, providerSecret);
let candleCount = 5;
if (cacheTicker.reset === true) {
candleCount = -1;
}
this.exchangeData.getCandles(cacheTicker.source, cacheTicker.symbol, cacheTicker.interval, 0, candleCount).then(async candles => {
const database = require("../utilities/Database"); // Add the ticker and interval data to each candle
candles.filter(candle => {
candle.symbol = cacheTicker.symbol;
candle.interval = cacheTicker.interval;
});
if (config.server.debugMode) {
console.log("Latest candle: ", candles[candles.length - 1]);
}
/**
* If the cache ticker is set to reset, then
* delete all candles and restore them. If not
* then upsert the 5 candles received.
*/
if (cacheTicker.reset === true) {
//await database.deleteCandles(providerName, cacheTicker.source, cacheTicker.symbol, cacheTicker.interval);
await database.insertCandles(providerName, cacheTicker.source, candles);
} else {
await database.upsertCandles(providerName, cacheTicker.source, cacheTicker.symbol, cacheTicker.interval, candles);
}
await database.updateCacheTicker(cacheTicker._id, {
reset: false
});
if (config.server.debugMode) {
console.log("Fetched CandlesCount: ", candles.length);
}
self.exchangeDataLocks[exchangeDataLockName].release();
}).catch(function (error) {
console.error(error);
});
}
}
module.exports = new Scheduler();