Files
Superalgos/IndicatorBotMarket.js
T

252 lines
11 KiB
JavaScript

exports.newIndicatorBotMarket = function newIndicatorBotMarket(bot, logger, COMMONS, UTILITIES, FILE_STORAGE) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
const MODULE_NAME = "User Bot";
const BOLLINGER_CHANNELS_FOLDER_NAME = "Bollinger-Channels";
const BOLLINGER_STANDARD_CHANNELS_FOLDER_NAME = "Bollinger-Standard-Channels";
const BOLLINGER_SUB_CHANNELS_FOLDER_NAME = "Bollinger-Sub-Channels";
const BOLLINGER_STANDARD_SUB_CHANNELS_FOLDER_NAME = "Bollinger-Standard-Sub-Channels";
const commons = COMMONS.newIndicatorBotCommons(bot, logger, UTILITIES);
thisObject = {
initialize: initialize,
start: start
};
let fileStorage = FILE_STORAGE.newFileStorage(logger);
let processConfig;
return thisObject;
function initialize(pProcessConfig, callBackFunction) {
try {
logger.fileName = MODULE_NAME;
logger.initialize();
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
processConfig = pProcessConfig;
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function start(dataFiles, timePeriod, outputPeriodLabel, startDate, endDate, callBackFunction) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
let market = global.MARKET;
let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies
for (let i = 0; i < dataDependencies.length; i++) {
let dataset = dataDependencies[i].referenceParent
let dataFile = dataFiles[i]
let jsonData // Datafile converted into Json objects
let inputData // Includes calculated properties
let variableName // name of the variable for this product
let recordDefinition
/*
For each dataset in our data dependencies, we should have da dataFile containing the records needed as an imput for this process.
What we need to do first is transform those records into JSON objects that can be used by user-defined formulas.
The first step does that but with the not calculated properties, the second step adds the calculated properties.
*/
/* Basic validations to see if we have everything we need. */
if (dataset.parentNode.code.variableName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataset.parentNode.record === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(dataset.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataset.parentNode.calculations === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Calculations Procedure. Product Definition = " + JSON.stringify(dataset.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataset.parentNode.dataBuilding === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Data Building Procedure. Product Definition = " + JSON.stringify(dataset.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
recordDefinition = dataset.parentNode.record
variableName = dataset.parentNode.code.variableName
/* Transform the raw data into JSON objects */
jsonData = commons.jsonifyDataFile(dataFile, recordDefinition)
/* Add the calculated properties */
if (dataset.parentNode.calculations !== undefined) {
inputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, variableName, timePeriod)
}
}
/* During the next phase, we need to generate the data of the different products this process produces an output */
let dataFile;
let bands = [];
let channels = [];
let standardChannels = [];
let subChannels = [];
let standardSubChannels = [];
dataFile = dataFiles[0]; // We only need the bollinger bands.
commons.buildBandsArray(dataFile, bands, timePeriod, callBackFunction);
commons.buildChannels(bands, channels, callBackFunction);
commons.buildStandardChannels(bands, standardChannels, callBackFunction);
commons.buildSubChannels(bands, subChannels, callBackFunction);
commons.buildStandardSubChannels(bands, standardSubChannels, callBackFunction);
let dataDependency = {}
for (let i = 0; i < processConfig.dataDependencies.length; i++) {
let dependency = processConfig.dataDependencies[i]
let recordDefinition = processConfig.recordDefinition
let dependencyArray = commons.buildDependencyArray(dataFiles[i], recordDefinition);
dependencyArray = commons.addCalculatedProperties(dependencyArray, dependency.singularVariableName, timePeriod);
dataDependency[dependency.pluralVariableName] = dependencyArray
}
for (let i = 0; i < processConfig.updatesDatasets.length; i++) {
let product = processConfig.updatesDatasets[i].product
let dataset = processConfig.updatesDatasets[i].dataset
let recordDefinition = getRecordDefinition(product)
let records = commons.buildRecords(dataDependency, recordDefinition)
let fileContent = generateFileContent(indicatorData, recordDefinition)
writeFile(product, dataset, fileContent)
}
let totalFilesWritten = 0
function anotherFileWritten() {
totalFilesWritten++
if (totalFilesWritten === processConfig.updatesDatasets.length) {
callBackFunction(global.DEFAULT_OK_RESPONSE);
}
}
function getRecordDefinition(product) {
for (let j = 0; j < bot.products.length; j++) {
if (bot.products[j].codeName === product) {
return bot.products[j].recordDefinition
}
}
}
function generateFileContent(records, recordDefinition) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> generateFileContent -> Entering function."); }
let fileContent = "";
let recordSeparator = "";
for (let i = 0; i < records.length; i++) {
let record = records[i];
fileContent = fileContent + recordSeparator + '['
let propertySeparator = ""
for (let j = 0; j < recordDefinition.length; j++) {
let property = recordDefinition[j]
fileContent = fileContent + propertySeparator
if (property.isNumeric !== true) {
fileContent = fileContent + '"'
}
fileContent = fileContent + record[property.name]
if (property.isNumeric !== true) {
fileContent = fileContent + '"'
}
if (recordSeparator === "") { propertySeparator = ","; }
}
fileContent = fileContent + ']'
if (recordSeparator === "") { recordSeparator = ","; }
}
fileContent = "[" + fileContent + "]";
return fileContent
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> generateFileContent -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeFile(product, dataset, fileContent) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFile -> Entering function."); }
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + product + "/" + dataset + "/" + outputPeriodLabel;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
anotherFileWritten();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
};