From 60307250297007b648b4bc5a435cf29640a796cd Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 18 May 2021 18:11:24 +0200 Subject: [PATCH 01/12] All volume related stuff removed from code --- .../FromOneMinToMultiPeriodMarket.js | 308 +++--------------- 1 file changed, 46 insertions(+), 262 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index fa3d355fb..348b8f8c7 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -26,8 +26,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process const MODULE_NAME = "From One Min To Multi Period Market" const DEPENDENCY_FOLDER_NAME = "Candles" const DEPENDENCY_ONE_MIN = "One-Min" - const VOLUMES_FOLDER_NAME = "Volumes" - const VOLUMES_ONE_MIN = "One-Min" let thisObject = { initialize: initialize, @@ -272,7 +270,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let n = 0 // loop Variable representing each possible period as defined at the periods array. let allPreviousCandles = [] // Each item of this array is an array of candles for a certain time frame - let allPreviousVolumes = [] // Each item of this array is an array of volumes for a certain time frame loopBody() @@ -282,7 +279,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process "[INFO] start -> findPreviousContent -> loopBody -> timeFrame = " + timeFrame) let previousCandles - let previousVolumes getCandles() @@ -308,7 +304,9 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process try { candlesFile = JSON.parse(text); previousCandles = candlesFile; - getVolumes(); + allPreviousCandles.push(previousCandles); + + controlLoop(); } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, @@ -328,53 +326,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } } - - function getVolumes() { - let fileName = 'Data.json'; - let filePath = - TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + - "/Output/" + - VOLUMES_FOLDER_NAME + "/" + - TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName + "/" + - timeFrame; - filePath += '/' + fileName - - fileStorage.getTextFile(filePath, onFileReceived); - - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> findPreviousContent -> loopBody -> getVolumes -> getting file."); - - function onFileReceived(err, text) { - let volumesFile - - if (err.result === TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { - try { - volumesFile = JSON.parse(text); - previousVolumes = volumesFile; - allPreviousCandles.push(previousCandles); - allPreviousVolumes.push(previousVolumes); - - controlLoop(); - - } catch (err) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getVolumes -> onFileReceived -> fileName = " + fileName); - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getVolumes -> onFileReceived -> filePath = " + filePath); - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getVolumes -> onFileReceived -> err = " + err.stack); - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getVolumes -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); - } - } else { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getVolumes -> onFileReceived -> err = " + err.stack); - callBackFunction(err); - } - } - } - } function controlLoop() { @@ -382,7 +333,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length) { loopBody() } else { - buildCandles(allPreviousCandles, allPreviousVolumes); + buildCandles(allPreviousCandles); } } } @@ -394,7 +345,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } - function buildCandles(allPreviousCandles, allPreviousVolumes) { + function buildCandles(allPreviousCandles) { try { let fromDate = new Date(contextVariables.datetimeLastProducedFile.valueOf()) @@ -403,13 +354,11 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process Firstly we prepere the arrays that will accumulate all the information for each output file. */ let outputCandles = []; - let outputVolumes = []; for (let n = 0; n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length; n++) { const emptyArray1 = []; const emptyArray2 = []; outputCandles.push(emptyArray1); - outputVolumes.push(emptyArray2); } advanceTime() @@ -461,11 +410,9 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process function loopBody() { let previousCandles // This is an array with all the elements already existing for a certain time frame. - let previousVolumes if (allPreviousCandles !== undefined) { previousCandles = allPreviousCandles[n]; - previousVolumes = allPreviousVolumes[n]; } const outputPeriod = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][0]; @@ -504,28 +451,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } allPreviousCandles[n] = [] // erasing these so as not to duplicate them. } - - if (previousVolumes !== undefined && previousVolumes.length !== 0) { - - for (let i = 0; i < previousVolumes.length; i++) { - let volume = { - begin: previousVolumes[i][2], - end: previousVolumes[i][3], - buy: previousVolumes[i][0], - sell: previousVolumes[i][1] - } - - if (volume.end < contextVariables.datetimeLastProducedFile.valueOf()) { - - outputVolumes[n].push(volume); - - } else { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> timeframesLoop -> loopBody -> Volume # " + i + " @ " + timeFrame + " discarded for closing past the current process time.") - } - } - allPreviousVolumes[n] = []; // erasing these so as not to duplicate them. - } /* From here on is where every iteration of the loop fully runs. Here is where we read Exchange Raw Data's files and add their content to whatever @@ -644,7 +569,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process outputCandles[n].push(outputCandle); } } - nextVolumeFile(); + writeFile(outputCandles[n], timeFrame, controlLoop); } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err @@ -654,106 +579,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } } - - function nextVolumeFile() { - try { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> timeframesLoop -> loopBody -> nextVolumeFile -> Entering function.") - - let dateForPath = - contextVariables.datetimeLastProducedFile.getUTCFullYear() + '/' + - TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCMonth() + 1, 2) + '/' + - TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2); - let fileName = "Data.json" - - let filePathRoot = - 'Project/' + - TS.projects.superalgos.globals.taskConstants.PROJECT_DEFINITION_NODE.config.codeName + "/" + - TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.type.replace(' ', '-') + "/" + - TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName + "/" + - "Exchange-Raw-Data" + '/' + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + "/" + - TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "-" + - TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName - let filePath = filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + '/' + VOLUMES_ONE_MIN + '/' + dateForPath; - filePath += '/' + fileName - fileStorage.getTextFile(filePath, onFileReceived); - - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> timeframesLoop -> loopBody -> nextVolumeFile -> getting file at dateForPath = " + dateForPath); - - function onFileReceived(err, text) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> timeframesLoop -> loopBody -> nextVolumeFile -> onFileReceived -> Entering function.") - - let volumesFile - if (err.result === TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { - try { - volumesFile = JSON.parse(text); - - } catch (err) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextVolumeFile -> onFileReceived -> Error Parsing JSON -> err = " + err.stack); - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextVolumeFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); - return; - } - } else { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextVolumeFile -> onFileReceived -> Error Received -> err = " + err.stack); - callBackFunction(err); - return; - } - const inputVolumesPerdiod = 60 * 1000; // 1 min - const inputFilePeriod = 24 * 60 * 60 * 1000; // 24 hs - - let totalOutputVolumes = inputFilePeriod / outputPeriod; // this should be 2 in this case. - let beginingOutputTime = contextVariables.datetimeLastProducedFile.valueOf(); - - for (let i = 0; i < totalOutputVolumes; i++) { - let outputVolume = { - buy: 0, - sell: 0, - begin: 0, - end: 0 - } - - let saveVolume = false; - outputVolume.begin = beginingOutputTime + i * outputPeriod; - outputVolume.end = beginingOutputTime + (i + 1) * outputPeriod - 1; - - for (let j = 0; j < volumesFile.length; j++) { - let volume = { - buy: volumesFile[j][0], - sell: volumesFile[j][1], - begin: volumesFile[j][2], - end: volumesFile[j][3] - } - - /* Here we discard all the Volumes out of range. */ - if (volume.begin >= outputVolume.begin && volume.end <= outputVolume.end) { - - saveVolume = true; - - outputVolume.buy = outputVolume.buy + volume.buy; - outputVolume.sell = outputVolume.sell + volume.sell; - } - } - - if (saveVolume === true) { - outputVolumes[n].push(outputVolume); - } - } - - writeFiles(outputCandles[n], outputVolumes[n], timeFrame, controlLoop); - } - } catch (err) { - TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextVolumeFile -> onFileReceived -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); - } - } } function controlLoop() { @@ -776,106 +601,65 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } - function writeFiles(candles, volumes, timeFrame, callBack) { + function writeFile(candles, timeFrame, callBack) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFiles -> Entering function.") + "[INFO] start -> writeFile -> Entering function.") /* - Here we will write the contents of the Candles and Volumens files. + Here we will write the contents of the file to disk. */ try { - writeCandles() - function writeCandles() { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[INFO] start -> writeFile -> writeCandles -> Entering function.") - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFiles -> writeCandles -> Entering function.") + let separator = "" + let fileRecordCounter = 0 + let fileContent = "" - let separator = "" - let fileRecordCounter = 0 - let fileContent = "" - - for (let i = 0; i < candles.length; i++) { - let candle = candles[i]; - fileContent = fileContent + separator + '[' + candles[i].min + "," + candles[i].max + "," + candles[i].open + "," + candles[i].close + "," + candles[i].begin + "," + candles[i].end + "]"; - if (separator === "") { separator = ","; } - fileRecordCounter++ - } - - fileContent = "[" + fileContent + "]"; - - let fileName = 'Data.json'; - let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + - "/Output/" + - DEPENDENCY_FOLDER_NAME + "/" + - TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName + "/" + - timeFrame - filePath += '/' + fileName - - fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated); - - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFiles -> writeCandles -> creating file at filePath = " + filePath); - - function onFileCreated(err) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFiles -> writeCandles -> onFileCreated -> Entering function.") - - if (err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeFiles -> writeCandles -> onFileCreated -> err = " + err.stack) - callBackFunction(err) - return - } - - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> writeFiles -> writeCandles -> onFileCreated -> Finished with File @ " + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "_" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName + ", " + fileRecordCounter + " records inserted into " + filePath + "/" + fileName) - writeVolumes() - } + for (let i = 0; i < candles.length; i++) { + let candle = candles[i]; + fileContent = fileContent + separator + '[' + candles[i].min + "," + candles[i].max + "," + candles[i].open + "," + candles[i].close + "," + candles[i].begin + "," + candles[i].end + "]"; + if (separator === "") { separator = ","; } + fileRecordCounter++ } - function writeVolumes() { - let separator = ""; - let fileRecordCounter = 0; - let fileContent = ""; + fileContent = "[" + fileContent + "]"; - for (let i = 0; i < volumes.length; i++) { - let candle = volumes[i]; - fileContent = fileContent + separator + '[' + volumes[i].buy + "," + volumes[i].sell + "," + volumes[i].begin + "," + volumes[i].end + "]"; - if (separator === "") { separator = ","; } - fileRecordCounter++ + let fileName = 'Data.json'; + let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + + "/Output/" + + DEPENDENCY_FOLDER_NAME + "/" + + TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName + "/" + + timeFrame + filePath += '/' + fileName + + fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated); + + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[INFO] start -> writeFile -> writeCandles -> creating file at filePath = " + filePath); + + function onFileCreated(err) { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[INFO] start -> writeFile -> writeCandles -> onFileCreated -> Entering function.") + + if (err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[ERROR] start -> writeFile -> writeCandles -> onFileCreated -> err = " + err.stack) + callBackFunction(err) + return } - fileContent = "[" + fileContent + "]"; - - let fileName = 'Data.json'; - let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + "/Output/" + VOLUMES_FOLDER_NAME + "/" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName + "/" + timeFrame; - filePath += '/' + fileName - - fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated); - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFiles -> writeVolumes -> creating file at filePath = " + filePath); - - function onFileCreated(err) { - if (err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeFiles -> writeVolumes -> onFileCreated -> err = " + err.stack); - callBackFunction(err); - return; - } - - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> writeFiles -> writeVolumes -> onFileCreated -> Finished with File @ " + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "_" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName + ", " + fileRecordCounter + " records inserted into " + filePath + "/" + fileName); - - callBack() - } + "[WARN] start -> writeFile -> writeCandles -> onFileCreated -> Finished with File @ " + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "_" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName + ", " + fileRecordCounter + " records inserted into " + filePath + "/" + fileName) + callBack() } + } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeFiles -> err = " + err.stack); + "[ERROR] start -> writeFile -> err = " + err.stack); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } From 2b076c7c41329d98a4c1475630fe5fa10159e16d Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 18 May 2021 18:19:39 +0200 Subject: [PATCH 02/12] removing referencies to Candle --- .../FromOneMinToMultiPeriodMarket.js | 180 +++++++++--------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index 348b8f8c7..6f2bcf12a 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -2,8 +2,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process /* This process is going to do the following: - Read the elements (candles, volumens, bolllinger bands, news, asset metrics, etc.) from a - One-Min dataset (a dataset that is organized with elements spanning one min, like one min candles, + Read the elements (elements, volumens, bolllinger bands, news, asset metrics, etc.) from a + One-Min dataset (a dataset that is organized with elements spanning one min, like one min elements, or elements with a timestamp captured approximatelly one minute from each other), and the dataset itself organized in Daily Files. @@ -19,7 +19,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process 2. Then it will append to these arrays the new information it gets from the data dependency. 3. It knows from it's status report which was the last DAY it processed. Since that day might not have been - full of that (maybe it was at the head of the market). The process will have to be carefull not to append candles + full of that (maybe it was at the head of the market). The process will have to be carefull not to append elements that are already there. To take care of that, it will discard all elements of the last processed day, and then it will process that full day again adding all the elements found at the current run. */ @@ -206,7 +206,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process contextVariables.datetimeLastProducedFile.valueOf() - TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); // Go back one day to start well. - buildCandles() + buildOutput() return } @@ -240,7 +240,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process contextVariables.datetimeLastProducedFile.valueOf() - TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); // Go back one day to start well. - buildCandles() + buildOutput() return } @@ -269,7 +269,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process try { let n = 0 // loop Variable representing each possible period as defined at the periods array. - let allPreviousCandles = [] // Each item of this array is an array of candles for a certain time frame + let allPreviousElements = [] // Each item of this array is an array of elements for a certain time frame loopBody() @@ -278,7 +278,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> loopBody -> timeFrame = " + timeFrame) - let previousCandles + let previousElements getCandles() @@ -298,13 +298,13 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process "[INFO] start -> findPreviousContent -> loopBody -> getCandles -> getting file."); function onFileReceived(err, text) { - let candlesFile + let dailyFile if (err.result === TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { try { - candlesFile = JSON.parse(text); - previousCandles = candlesFile; - allPreviousCandles.push(previousCandles); + dailyFile = JSON.parse(text); + previousElements = dailyFile; + allPreviousElements.push(previousElements); controlLoop(); @@ -333,7 +333,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length) { loopBody() } else { - buildCandles(allPreviousCandles); + buildOutput(allPreviousElements); } } } @@ -345,7 +345,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } - function buildCandles(allPreviousCandles) { + function buildOutput(allPreviousElements) { try { let fromDate = new Date(contextVariables.datetimeLastProducedFile.valueOf()) @@ -353,12 +353,12 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process /* Firstly we prepere the arrays that will accumulate all the information for each output file. */ - let outputCandles = []; + let outputElements = []; for (let n = 0; n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length; n++) { const emptyArray1 = []; const emptyArray2 = []; - outputCandles.push(emptyArray1); + outputElements.push(emptyArray1); } advanceTime() @@ -373,13 +373,13 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process contextVariables.datetimeLastProducedFile = new Date(contextVariables.datetimeLastProducedFile.valueOf() + TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> advanceTime -> New processing time @ " + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") + "[INFO] start -> buildOutput -> advanceTime -> New processing time @ " + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") /* Validation that we are not going past the head of the market. */ if (contextVariables.datetimeLastProducedFile.valueOf() > contextVariables.datetimeLastAvailableDependencyFile.valueOf()) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> advanceTime -> Head of the market found @ " + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") + "[INFO] start -> buildOutput -> advanceTime -> Head of the market found @ " + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE); // Here is where we finish processing and wait for the platform to run this module again. return @@ -409,10 +409,10 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process loopBody() function loopBody() { - let previousCandles // This is an array with all the elements already existing for a certain time frame. + let previousElements // This is an array with all the elements already existing for a certain time frame. - if (allPreviousCandles !== undefined) { - previousCandles = allPreviousCandles[n]; + if (allPreviousElements !== undefined) { + previousElements = allPreviousElements[n]; } const outputPeriod = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][0]; @@ -420,36 +420,36 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process /* Here we are inside a Loop that is going to advance 1 day at the time, at each pass, we will read one of Exchange Raw Data's daily files and - add all its candles to our in memory arrays. + add all its elements to our in memory arrays. - At the first iteration of this loop, we will add the candles that we are carrying + At the first iteration of this loop, we will add the elements that we are carrying from our previous run, the ones we already have in-memory. You can see below how we discard the elements that belong to the first day we are processing at this run, that it is exactly the same as the last day processed the previous - run. By discarding these candles, we are ready to run after that standard - function that will just add ALL the candles found each day at Exchange Raw Data. + run. By discarding these elements, we are ready to run after that standard + function that will just add ALL the elements found each day at Exchange Raw Data. */ - if (previousCandles !== undefined && previousCandles.length !== 0) { - for (let i = 0; i < previousCandles.length; i++) { - let candle = { - open: previousCandles[i][2], - close: previousCandles[i][3], - min: previousCandles[i][0], - max: previousCandles[i][1], - begin: previousCandles[i][4], - end: previousCandles[i][5] + if (previousElements !== undefined && previousElements.length !== 0) { + for (let i = 0; i < previousElements.length; i++) { + let element = { + open: previousElements[i][2], + close: previousElements[i][3], + min: previousElements[i][0], + max: previousElements[i][1], + begin: previousElements[i][4], + end: previousElements[i][5] } - if (candle.end < contextVariables.datetimeLastProducedFile.valueOf()) { - outputCandles[n].push(candle); + if (element.end < contextVariables.datetimeLastProducedFile.valueOf()) { + outputElements[n].push(element); } else { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> timeframesLoop -> loopBody -> Candle # " + i + " @ " + timeFrame + " discarded for closing past the current process time.") + "[INFO] start -> buildOutput -> timeframesLoop -> loopBody -> Element # " + i + " @ " + timeFrame + " discarded for closing past the current process time.") } } - allPreviousCandles[n] = [] // erasing these so as not to duplicate them. + allPreviousElements[n] = [] // erasing these so as not to duplicate them. } /* From here on is where every iteration of the loop fully runs. Here is where we @@ -458,9 +458,9 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process many days needed and it should only stop when it reaches the head of the market. */ - nextCandleFile(); + nextDailyFile(); - function nextCandleFile() { + function nextDailyFile() { let dateForPath = contextVariables.datetimeLastProducedFile.getUTCFullYear() + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCMonth() + 1, 2) + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2); let fileName = "Data.json" @@ -478,20 +478,20 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process fileStorage.getTextFile(filePath, onFileReceived); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> timeframesLoop -> loopBody -> nextCandleFile -> getting file at dateForPath = " + dateForPath); + "[INFO] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> getting file at dateForPath = " + dateForPath); function onFileReceived(err, text) { try { - let candlesFile + let dailyFile if (err.result === TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { try { - candlesFile = JSON.parse(text); + dailyFile = JSON.parse(text); } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextCandleFile -> onFileReceived -> Error Parsing JSON -> err = " + err.stack); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Error Parsing JSON -> err = " + err.stack); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextCandleFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); return } @@ -500,31 +500,31 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (err.message === 'File does not exist.' || err.code === 'The specified key does not exist.') { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> buildCandles -> timeframesLoop -> loopBody -> nextCandleFile -> onFileReceived -> Dependency Not Ready -> err = " + JSON.stringify(err)); + "[WARN] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Dependency Not Ready -> err = " + JSON.stringify(err)); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> buildCandles -> timeframesLoop -> loopBody -> nextCandleFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); + "[WARN] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); return } else { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextCandleFile -> onFileReceived -> Error Received -> err = " + err.stack); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Error Received -> err = " + err.stack); callBackFunction(err) return } } - const inputCandlesPerdiod = 60 * 1000; // 1 min + const inputElementPerdiod = 60 * 1000; // 1 min const inputFilePeriod = 24 * 60 * 60 * 1000; // 24 hs - let totalOutputCandles = inputFilePeriod / outputPeriod; // this should be 2 in this case. + let totaloutputElements = inputFilePeriod / outputPeriod; // this should be 2 in this case. let beginingOutputTime = contextVariables.datetimeLastProducedFile.valueOf(); /* - The algorithm that follows is going to agregate candles of 1 min timeFrame read from Exchange Raw Data, into candles of each timeFrame + The algorithm that follows is going to agregate elements of 1 min timeFrame read from Exchange Raw Data, into elements of each timeFrame that Candles Volumes generates. For market files those timePediods goes from 1h to 24hs. */ - for (let i = 0; i < totalOutputCandles; i++) { + for (let i = 0; i < totaloutputElements; i++) { - let outputCandle = { + let outputElement = { open: 0, close: 0, min: 0, @@ -533,48 +533,48 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process end: 0 }; - let saveCandle = false; - outputCandle.begin = beginingOutputTime + i * outputPeriod; - outputCandle.end = beginingOutputTime + (i + 1) * outputPeriod - 1; + let saveElement = false; + outputElement.begin = beginingOutputTime + i * outputPeriod; + outputElement.end = beginingOutputTime + (i + 1) * outputPeriod - 1; - for (let j = 0; j < candlesFile.length; j++) { - let candle = { - open: candlesFile[j][2], - close: candlesFile[j][3], - min: candlesFile[j][0], - max: candlesFile[j][1], - begin: candlesFile[j][4], - end: candlesFile[j][5] + for (let j = 0; j < dailyFile.length; j++) { + let element = { + open: dailyFile[j][2], + close: dailyFile[j][3], + min: dailyFile[j][0], + max: dailyFile[j][1], + begin: dailyFile[j][4], + end: dailyFile[j][5] } - /* Here we discard all the candles out of range. */ - if (candle.begin >= outputCandle.begin && candle.end <= outputCandle.end) { + /* Here we discard all the elements out of range. */ + if (element.begin >= outputElement.begin && element.end <= outputElement.end) { - if (saveCandle === false) { // this will set the value only once. - outputCandle.open = candle.open; - outputCandle.min = candle.min; - outputCandle.max = candle.max; + if (saveElement === false) { // this will set the value only once. + outputElement.open = element.open; + outputElement.min = element.min; + outputElement.max = element.max; } - saveCandle = true; - outputCandle.close = candle.close; // only the last one will be saved - if (candle.min < outputCandle.min) { - outputCandle.min = candle.min; + saveElement = true; + outputElement.close = element.close; // only the last one will be saved + if (element.min < outputElement.min) { + outputElement.min = element.min; } - if (candle.max > outputCandle.max) { - outputCandle.max = candle.max; + if (element.max > outputElement.max) { + outputElement.max = element.max; } } } - if (saveCandle === true) { // then we have a valid candle, otherwise it means there were no candles to fill this one in its time range. - outputCandles[n].push(outputCandle); + if (saveElement === true) { // then we have a valid element, otherwise it means there were no elements to fill this one in its time range. + outputElements[n].push(outputElement); } } - writeFile(outputCandles[n], timeFrame, controlLoop); + writeFile(outputElements[n], timeFrame, controlLoop); } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> timeframesLoop -> loopBody -> nextCandleFile -> onFileReceived -> err = " + err.stack); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> err = " + err.stack); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } @@ -584,7 +584,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process function controlLoop() { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildCandles -> timeframesLoop -> controlLoop -> Entering function.") + "[INFO] start -> buildOutput -> timeframesLoop -> controlLoop -> Entering function.") n++ if (n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length) { loopBody() @@ -596,12 +596,12 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildCandles -> err = " + err.stack); + "[ERROR] start -> buildOutput -> err = " + err.stack); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } - function writeFile(candles, timeFrame, callBack) { + function writeFile(elements, timeFrame, callBack) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] start -> writeFile -> Entering function.") @@ -611,15 +611,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process try { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFile -> writeCandles -> Entering function.") + "[INFO] start -> writeFile -> Entering function.") let separator = "" let fileRecordCounter = 0 let fileContent = "" - for (let i = 0; i < candles.length; i++) { - let candle = candles[i]; - fileContent = fileContent + separator + '[' + candles[i].min + "," + candles[i].max + "," + candles[i].open + "," + candles[i].close + "," + candles[i].begin + "," + candles[i].end + "]"; + for (let i = 0; i < elements.length; i++) { + let element = elements[i]; + fileContent = fileContent + separator + '[' + elements[i].min + "," + elements[i].max + "," + elements[i].open + "," + elements[i].close + "," + elements[i].begin + "," + elements[i].end + "]"; if (separator === "") { separator = ","; } fileRecordCounter++ } @@ -637,21 +637,21 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFile -> writeCandles -> creating file at filePath = " + filePath); + "[INFO] start -> writeFile -> creating file at filePath = " + filePath); function onFileCreated(err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFile -> writeCandles -> onFileCreated -> Entering function.") + "[INFO] start -> writeFile -> onFileCreated -> Entering function.") if (err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeFile -> writeCandles -> onFileCreated -> err = " + err.stack) + "[ERROR] start -> writeFile -> onFileCreated -> err = " + err.stack) callBackFunction(err) return } TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> writeFile -> writeCandles -> onFileCreated -> Finished with File @ " + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "_" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName + ", " + fileRecordCounter + " records inserted into " + filePath + "/" + fileName) + "[WARN] start -> writeFile -> onFileCreated -> Finished with File @ " + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "_" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName + ", " + fileRecordCounter + " records inserted into " + filePath + "/" + fileName) callBack() } From d18f8cefd752e87cf1c3a986e037719b2a0b1c3b Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 18 May 2021 19:07:45 +0200 Subject: [PATCH 03/12] Hooking the new Framework module to the Indicator Bot --- .../FromOneMinToMultiPeriodMarket.js | 31 +++++++++++-------- .../Indicator-Bot/MultiPeriodMarket.js | 4 +-- .../Indicator-Bot/SingleMarketIndicatorBot.js | 10 ++++++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index 6f2bcf12a..dc8b2976d 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -29,25 +29,31 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let thisObject = { initialize: initialize, + finalize: finalize, start: start } - let fileStorage = TS.projects.superalgos.taskModules.fileStorage.newFileStorage(processIndex); - let statusDependencies; + let fileStorage = TS.projects.superalgos.taskModules.fileStorage.newFileStorage(processIndex) + + let statusDependencies + let dataDependenciesModule let beginingOfMarket return thisObject; - function initialize(pStatusDependencies, callBackFunction) { - try { - statusDependencies = pStatusDependencies; - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE); - } catch (err) { - TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] initialize -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); - } + function initialize(pStatusDependencies, pDataDependencies, callBackFunction) { + + statusDependencies = pStatusDependencies + dataDependenciesModule = pDataDependencies + + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE) + } + + function finalize() { + fileStorage = undefined + statusDependencies = undefined + dataDependenciesModule = undefined + thisObject = undefined } function start(callBackFunction) { @@ -69,7 +75,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let statusReport; /* We look first for Exchange Raw Data in order to get when the market starts. */ - reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/MultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/MultiPeriodMarket.js index 7c1e0ba5b..1583b4eb9 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/MultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/MultiPeriodMarket.js @@ -21,8 +21,8 @@ function initialize(pStatusDependencies, pDataDependencies, callBackFunction) { - statusDependencies = pStatusDependencies; - dataDependenciesModule = pDataDependencies; + statusDependencies = pStatusDependencies + dataDependenciesModule = pDataDependencies indicatorOutputModule = TS.projects.superalgos.botModules.indicatorOutput.newSuperalgosBotModulesIndicatorOutput(processIndex) indicatorOutputModule.initialize(callBackFunction) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/SingleMarketIndicatorBot.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/SingleMarketIndicatorBot.js index 9387e65c7..b0a052b75 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/SingleMarketIndicatorBot.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/SingleMarketIndicatorBot.js @@ -285,6 +285,16 @@ intitializeProcessFramework(); break; } + case 'From-One-Min-To-Multi-Period-Market': { + processFramework = TS.projects.superalgos.botModules.multiPeriodMarket.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket(processIndex); + intitializeProcessFramework(); + break; + } + case 'From-One-Min-To-Multi-Period-Daily': { + processFramework = TS.projects.superalgos.botModules.multiPeriodMarket.newSuperalgosBotModulesFromOneMinToMultiPeriodDaily(processIndex); + intitializeProcessFramework(); + break; + } default: { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework not Supported."); From 2bccf3518ce537aab1b8bc53c489b22f044b6b8a Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 18 May 2021 20:36:27 +0200 Subject: [PATCH 04/12] Some Icons for API Data Fetcher Bot and getContextVariables function implementation --- .../Icons-SVG-Sources/nodes/api-endpoint.svg | 8 + .../Icons-SVG-Sources/nodes/api-map.svg | 11 + .../nodes/api-path-parameter.svg | 13 + .../nodes/api-path-parameters.svg | 18 ++ .../nodes/api-query-parameter.svg | 7 + .../nodes/api-query-parameters.svg | 11 + .../nodes/api-query-responses.svg | 10 + .../Icons-SVG-Sources/nodes/api-version.svg | 10 + Projects/Superalgos/Icons/api-endpoint.png | Bin 0 -> 16000 bytes Projects/Superalgos/Icons/api-map.png | Bin 0 -> 17532 bytes .../Superalgos/Icons/api-path-parameter.png | Bin 0 -> 13511 bytes .../Superalgos/Icons/api-path-parameters.png | Bin 0 -> 13313 bytes .../Superalgos/Icons/api-query-parameter.png | Bin 0 -> 9747 bytes .../Superalgos/Icons/api-query-parameters.png | Bin 0 -> 12409 bytes .../Superalgos/Icons/api-query-responses.png | Bin 0 -> 18798 bytes Projects/Superalgos/Icons/api-version.png | Bin 0 -> 14640 bytes .../FromOneMinToMultiPeriodMarket.js | 236 +++++++++--------- .../Indicator-Bot/IndicatorOutput.js | 25 +- 18 files changed, 230 insertions(+), 119 deletions(-) create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-endpoint.svg create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-map.svg create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameter.svg create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameter.svg create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameters.svg create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-responses.svg create mode 100644 Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg create mode 100644 Projects/Superalgos/Icons/api-endpoint.png create mode 100644 Projects/Superalgos/Icons/api-map.png create mode 100644 Projects/Superalgos/Icons/api-path-parameter.png create mode 100644 Projects/Superalgos/Icons/api-path-parameters.png create mode 100644 Projects/Superalgos/Icons/api-query-parameter.png create mode 100644 Projects/Superalgos/Icons/api-query-parameters.png create mode 100644 Projects/Superalgos/Icons/api-query-responses.png create mode 100644 Projects/Superalgos/Icons/api-version.png diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-endpoint.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-endpoint.svg new file mode 100644 index 000000000..32243a131 --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-endpoint.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-map.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-map.svg new file mode 100644 index 000000000..ec357b88b --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-map.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameter.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameter.svg new file mode 100644 index 000000000..d1e49a8c6 --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameter.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg new file mode 100644 index 000000000..70c99224b --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameter.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameter.svg new file mode 100644 index 000000000..a5a1fc1c3 --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameter.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameters.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameters.svg new file mode 100644 index 000000000..4f55edae6 --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-parameters.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-responses.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-responses.svg new file mode 100644 index 000000000..1e76c91a2 --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-query-responses.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg new file mode 100644 index 000000000..76e1734df --- /dev/null +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Projects/Superalgos/Icons/api-endpoint.png b/Projects/Superalgos/Icons/api-endpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..ed3e662fbc8d4947f1347ccf321a3f17f2176909 GIT binary patch literal 16000 zcmch;XIPU>^C-RvU63w_w5T+tDTs6uZ1k>Dq=^*iAWdolilRIe5vdADFDeK~hoFLh zRO!_qAT_wKZvnVp%uFx1yLdE(3o0KiEt%^Su5 zz@dNPfSwlm*nT{C2z@YkX`1^0z{qj@2LowuPeYwBA7hPc;8PFZ67+@INnKAJfX{J^ zNB3y}P&=h{L;dz+*y}kE+6#B^`rI&4E`SrQ22F7_SbKiBr zuaxnY8yx+^-{J#*=d22f%54qrrk9OUzCRCC%PW~D`A)QHg(?hg9R!UxcoOx@@bX=T zy$ch2cbui?wrFgyRk$nNR2tn|{0}LYuoq*{ue*!-VOw85Rfbwpi25me?pWuS19tlLK(E&i`|bfkP`#Cmk$7##?a|BV#M!ei^pK=F=(vl?zSB4aambR1g< z10EOn&ppiDA0)K}!(^yl9{e!nmm>l&PyLc%Wub!I*6a%LV*;Rl zT?Z%myi2NSD0fg#wFsJ!JCw_tq2{#r@vv3)PSJ>{v(P^xK0FxPHp-q;+{^0K1oI=& zE`u?tVUG$R2W|3Egx|vFM7D%QT=asKOn5Vc41B6n7nFVdhAqB*Vt^EqlLkP-7l-Kt z-=7%~HAd%IYgj*=Tr?AbV{8Km?&($me{2HdKP`?SS$uv6(=43_ni+Kj6HnjGecNR0 z23vc%74LTIKysQn{AuDcK#cBS9|skCTO(TlQ!k?|=iIGhDDt*wo4t6fm7Qj&9m3a* zdBF$#;g_eWH-_iOlryo}*O^cjp>8=6eWazbZ<-E(^`Abb`W0-3 z`B8Ojz$S0*nvcLKkdU31b0E(D56ZfPj~XVOu_hvJdHO;(V7h&?ZZb8wp-m~MK}-ff zYhu4MVHWrk)&_IK@-B`VUZetYzD-4SXKA0KI${weDs+`OvI#kR*{9GT4`%}+u&|ZHh zK>zdP|lE|>!1wW;!(qTOR zbYy( zeNsN7!vGc|xF1#ANnlQ=MAV`0^u5xZqJ2mX7gbuOqmQM2=0f{{0U)fyh=eaO^GF6{ zvqmSAA7xGG3>dA{Z_5et3`z*QH(L}L7EvH|E zWFs(Z3W0|quNpbJDV4~Km`Cn8XU613o0un9Y`G|3ul|}sv;i2x(Pd6H-J?n=jYwEI z|BH(<-IHqWtaqkTp5a!vp_8r*59XG3LBqV$vk2*3T;}R_O4|uJ8GniG_^hh~xoH)^ z1rDNgh%regln)F9S%xuEa-UM=d6sOS)MQKKxm%TLnR5mM)*HUOdOn*ZhR_Y)rwPqT z3=9=s&+7#-5&*Q^T)J9Mk^Me@`IK|12ziKMDZI$-? zGa4`NU|;>1>b6RxPP-m)%{RQ5%AIWF3IW~mg9p>+L#c0=6E%y*&j<#oo{-m8Td{+P z?Hr1>RJyMNm(EZdan?fA?7t61qUwpTe{pqxZBwFo@14!&fWnNEF?q&7Q{&rPfzBqi z7t!uV19cMb%Bc`4o}<(-ettq(GVM~Wtg?LR*}%Be01nZb^G;oW_CuO+L`J9?f~>f9*j{n__5FnTC8L&sNA6Ru-nM)4|fM zvh#AAmJ@AO!F&7+=jkoK)O%ieZ!P{G{r>*Rf>-I^zS73{Qip}o#=FxGT?azhxYZV+D3>-UBEqsM7cp|-@9tUx>=;l?SxEqdJ2 z*pbib=hzsV!5E*MJ20?4sqG&2;ER4QaV6S`IdzYte9WRRg8@^DU(ClL#AhzRe6Mym zKgdWcZ5W0ZVsf) zs%2!EaAUix!IpKvC*q-bfu^WUe?->`9^foAC~*}dj=ZE1D76=+2qR>9V=o5~|>CnVGm> zbHkk$;ofvZ!Lf;|4UOIm+3@ynmv+KHd(ymRibcu?&-hK;!!m=BOiY#DpIWS)LKVo$ z3(W1!p9^?Vzv$L8e3;V}P7CZ!%c>H!MV0DQ9{TvV_j#N6r#J^Vsav-QfDc3MCmuiV z%3MB|XY6|Q`E43tc)I&Fm3+@8VY378Vbc?B`L4&OjS|Fu5?G`y@lUL?ZO%N`dn&;I zKzZrq`&9#9)#Ov<87cn+2Ise@w`WiT$?i?m-}#>d;RU0GKoJ;%lfRS+*pi zWxKInA0F0|cDAnoGx3^q^A6b7)$t*YOVf1Vk$6jUmR^|8<+MYkH)#+i_4!}doggbY zmg{7|&tVW*E7xaNjk~oB$9%aaApAkD=U|J42?TQS5q7!ckp$f6D)IprnP)h%J5LEb zWRUWUKm6mDPRlC_%clYH!QC&yMLqVND<-O=n=;OJ3tB_=Ey*v9*41T!Lzx;v{BXuO zc+ArLjO_iM*Ynb+Cs_Mc^yz^Z>%^6wJ@mhx8s^fuJ#eMe_U);>`7U&~&J@8cTo?%I;)HzSZ5UI4TX*RYSeNqFiGRQqpyg_kOsO@250<%!T` zpo5|CHvgn|GHUCk@6kb$WY3Y^NF|@Q^x#bFm@;U(K zcmI`F8Yt*L6pRgO4N;Ie1DvcdsHM5_Z?|F!RhgIW(N|}!LHN5&VE8zX$7m-_sJMky z2^#+&9@cjWQQPuw42D#0sBNn3$ifuP_G!`_`-A|3TiO$Yz9^kZ^YQv zBKS7xhGdtHJ}cBMqZPwf8SU-CHJ7VM4;mDI1zE5=kaeMv|MisJotpqKpvg#jzL%7T z6XdeG7~QYjEhBG#x9-mm=}$hMn1r;014r5SRmiaGiAd3=PesyANh@Kp(B3FV8pg29 zGjb(kQbxt+ELdKMYj>wFl%!=%EB@*nYM`Npc#P5gWm7w1eI46*^e|+~D%8@g3T1zb zYsY&h&(tNs`*_CS0LS06V@-aOA1vZhDIYWmV=`a8cUn#Jg>#P4EIK7|RPCW`ANF|E zISBU#A)b}*@Cz;CY7RRFVL3PK57tPQ)sV78e4W4saYHq@+)XV}*j!Go91D5TlfNiC z8AeOudcqdCfL2<#pK5AkKPI{!{Ak^Z)lLY(-7@2VgZ7voY-)bj++u8Wu8w83nuu-- zLJB^SMr6Q}Yg)+`pn8{(hhMJCOm}N5ojJ-L2(qLdq#^wcZWGR{Imrt8WMeES!#R!% zZmy&Raq%$>G2mrDpfP_@-tzo4$T`Ji&>NGh-5OaX$btE!?=zn7PLi80T!XOFd`sR8 z{eJbPN0@@dP1_1sl~8;(0s{@i7us$}cSP#?A86dCG?85Hq7T+?Q>z{mtYr~dw}*Kg zbd|%2ID1*h8t1m|w|M!O8s{S3Vc(_EeYSaS?F3hV?!!@5hD48C636GGyV!ltVeeJd?( zsGwOAS^1L|?p^de_Cd78v)sXeo{&)gJv&?007%a522>W1yr$nXt!k3dR}j(3RZlIp z>o1qhrn%Kp$~!ps*#Gd9P-4`diajfAjG3 zFaZt3B?+>>vN0t}C<=1h5nNwSTS}*_64n&;iqU_9tK03|qqnu)cwmwmgWO?Wy6ne< z_wx9%M)26f+H;Xga1#Reim@D3-d^iu@qW(;*z^*!?)aRVTcE#K+_E`&kM-#AQ%mnNN0qPJV+8%^bw(dv>OE)4JhE zvELI=p>c;KQzs!uduW!&n?WP*W+`&A^kmX*-h<4qmj&|izI0?s(cn03X%L^GpY*zSFydmuxO|f9^gl!qu)t&Dd1OG0})E-_K zjdd^VT%Pfy=?+H|)wpBAuX{Ve&Y_>TX4Lgsa5x>R@bT=8P*un-+AVjw8Z8`cB*5kzQQ&z zXo?LjnKPg3e^$Vv$#kq1tOjhFf)%v4GN(wQ-g%zVV_2J9Y|g>qGIUPsTmC%_d$(popgi!LxI3*@Y>f|j|Hbb_y<0aV&U-~*Pbw}0D zFfl~%b5Q$AUd#Hz#%(I07fmpQ6bj^P-ZrGfT}p93&}bbcRZFDHG$#dr(oTNnCWtvC z2{xRKy}=A16O>klph9gt4t028d+^cMW^2V_&NXI5#_qQ=BM^gRzb?mb0oRn4-U6liz(HEIg5p@=_z^^vW2KyMPb-@2QXABEcqXF>IA7u&oQ-h%E(RYj3iEcCjP6Y0;>n} zq6T;AVVJvHGsmVrOW9&RSI6bvWhzX6U%9UV6xIXAsFi?RonKtv@SEB8;KoSH*<+R` z-yY$?^sm|jrTi%?8n7y#EzfZngtV zTQEw2VkY_DRZItyt&39ktmN}|LKo9GJDT}lk(;)bqe~ULK}}8E=Zj%8&Tos4VKD8k zH(L7ETx$8+RoYX$3zgNR%$?_Ik-^b+jt(4KY_oV+Rto-GZXF|V(`!Jt$(e`vmCQ{w z$3_;KfRdTh!Vu7VNq)JX@uYwoqoJEq4k=TjH-+?D6(G^BJgn0})b z57%&eaXPyHj_tUo#>#NEpBeSmqg|`L7-&lo*o}H1q`rj{A7F=UAwbzLw@)@KF4hly zWwGfv(hK(=@uUd6I=E=;_d(+ANtOfhFQMK6WsG5)wr?g$*{i{C#DS7$Pr4u!37sr(^z9=?G3xE)c zKX;We3;T%RZFI3etej437zD7f>y$e5ic5&K03emElC*`H2TzMTUr!pb3nw6v=6*@USk2`a%l5fb*1Wb70<4cR3@ zjt;6$D^y%cUVIu2ng;_XeS`hCogmflb@NGUdgBmDeQm! zh_Kd%?!6aHmh6p%pBS0&1S6_>_uwgNcE6>1_c4j1oqhj9`OtnBYcA51)-b7*I7QIsh>ey##?HQq?vBNSqS{_LrJ4-j@WMCU_sEoVwNh{^` zBhlEKP)gv~AG)`xVL8bYe_@x9p3sUrM+Iq1hGWNdR*66Un#kg>;Gm)PYJvawTU^&Y zJEIf?xDv0m{cS9%AE?~FXAkjCwE!DJs7W0BW$8fW)`%N#z8q$o+66zD> zaQvf!NG&MYy_Q?KdN^_p8pzeoha9tCp0!~&NDGh^{|o7apxu`EcH3_nid^$U?O$8k zMBpGH2a@2Yk41RnBT)#=J!0G6&2OKr|Jhl6_5@7l9?)$byPIg^7geQQbt!2a9%;-VoMjW$0h{-Elq znHu!TW$IYtOWUiw( zcg8v(i}xQmZJ(_F=h8i$)`6gc(!sKWq$?q_JyUO1WWc9U-3SJzF8O{%>>5(Ell+!% z%!UI&Rl`J&vcpGUCkt+^_Wb6SJ2PU3%`k&wc7}8V@AnKmYLe3Nv1f?C3n?|b2P?Z& zdEqaOU6Sv*+|CWCnB-sr9=B!vB8v$ly`7tHE|RD<86oYXKXwya>bX*5eE3b2Bu2H)dG(zHuDE|`ObdYcSic?z$lnuLF@(O&`1ri|Tm*pxL8uG!| z_z_|$C``WpG_dSV-zDWa&G`^Z;6fNkpKC#*iCBI0E=SF{iq1&IEmiB|h>5^|hBu0DU$4YI!Oo>)BG z6#5IRfnc(=3N+upSI!4M{1RhPsr9tLMDgjuRTQQ2`e9nejpTpMj3Fh#+s=t^xP;dr zD-s1>)z&a(Nm!T)nfEe)g3Y@1h1=%QZw(DHRkLb_kZAksc=OSRGy{}64}UB2)14!L$RQ7RDqXtxj?`zAE@10*Wa zlZtGIbI}@yWiT6q#|H0eZwD=R)c|)xI5^RgPoxWx6Sjyuv3YTkWj!OvpW6ZE_KXP_ zva+acEM31k)jMOusct?E9|LYrnLxZx)i4f+e5`*EcGK{RJyqFR8Gwo%vp}OM!#Yl@|`To0S3xjWYvBgNptn`OYyhTW*&o8)Q4p_12pVpq*jjufb12ez9Qd zCAe_-45W=7H4hWt5Cl20Osa&|x5qB1|ADZQar+x3Xhn86f{(tvTU=b)SgjGu_m-Oz z&I1rR5sp~0`uzTPhTzZf@@1iS^YxQxAXWf-!<+#dsi?+SUatbT1sYarPAV9PzbrwH z;!#JbL#*fdHWT+0>IP6Zn*>?&v^uKiCX@qlGPo;rAd*{r=Kf=vmrq)eO8PM0k3R;R zLmqka+TK)=9#dy;^2C|ahygD2wpl#GdVxMW^&FEhK(v}2y<$(KdK3kn>kGg8xY(qrek$U{P*%FaS!p$xUbjG96A=OPNZF6~aXR^E>&qvp?Pd)zDMbx(A0X#-T;SRFDN zDdVB(zLdime;ERXg=T?NL_ANIID9IW))CUprxwzwALT~&8x;wr)K#sy-tm`_z&#Jp9 zoTkp5*Gs4nc~OoQiTCLKiaZ5lEz^MSj9|T!Lv~F(p@ixqkag=vY${6|b+aFBl7nR; zF#BF#71HOF;Cc}{6*JkI6e@X>Bg#49;|*160tjV&M|2+wBy5z;*|s5avC?5ZEy0J* zt%jFb3&(TB{u0>1O8?JUir@w4h$uMLQ}n1WNr2&@8bs84R3oHr6^46%A+sb)(JM7s z1&}+~rt&L}0n>fKv*15pE91#@*G`|>=7fQ1);0>J?^%mJ&5hn08PtVPe4EQaSQ$4q z(w5FaAD(#OGm-AvMXMshr)XWqpl@HTKu|lU&(8!gy*;u14*4at0V8JDw?ou+?W{Jy zT+b+Qc7tE*|E7YmhB(0|6HIvt=x_d#9x$N>nDgDVDDdYO{pfY(Ab^=UBf!tUOdv>4 z%p*DU2-$}$zCY^kX0BuX4;!M8(w&SxkLIQu5NwbXY5IRAtngl`50Qh+tCQ@MjR#37 z8rk>8yVqn^B#Mh?RO+xu)+hg}p^0DUFK(>1A*&!9*i!j_6%;#pJJGnlvOGG}wK>l5 zGo4*_7iFi5^7UD(Nlr#$Y*hq&i}JnLW-s&gU-3I|xI9E)IRPGiap}DxqrB}0#bbSK zb}ZX>&x`ea7cuctpr_AJyLTsy)PT)(nu9LUS>n_{Or?I2NcE`s!}e^G)>5#<0jij$ zn&D#U%*pmaZU5=F=9eM^mcaY{}81#uxn$kT`jk$q2m zEBdIR$*h!}sghd}N@>jH#Kqmw)@I(f>p#*>l;DJ8vN!TW(MvoBljLGsD`?-RbbGNe z=`3`ktK8f$)a8%%G#Qifk~PdQD1WgyBY0XR_lr`OhafeGG?iuiEfn5-5f0{<8Ii-+ z0Y(HK4!MJKFZFiPxp$22|4{Hi0Sqsv8Y=>zq((9?yENM&_f=7+UCxy!-b5L zR}p6cD*t3$%p2m$qlkI6N@$(#zyb11zx}INmPfn@nU$}iYN3VLPmbnCup0|;!BlxV zzcb&eUZhc{1*x(PdjsF8jFIYfg6|Mi80NvF*2A?1C#qv}ta?#fRYa@*u;I)F>qgph zEUUcA7cE4n7oi)u(tHsEC16iqTVJt;vH8E3e9E&x17L{wXn{395{Cn=^_{1CgQ*)0 zj#P^<)G}myDKHlj2+GBuOmx%{VU2$aLGCgZuEw%9fppMT8(`Xo^<3lorfa0)K+A_T2wL;!&xpI&bT?4=|m<% z#XiQug?rIgqmelwu-v<2ugT_wC6m-1Lw10WJEL(_xJT7azpCdD=mnu+9KJ;YG93b^ zx*oDZq|ONTB8)OXxwlk@Cm5y-RkJzy=FzKgB1v~7^azf*rtIwsyyEow&*fUDrt`C! z^KUkgds+_-%9w+h4qZiiI~R6M^V-B<&5HN-xO+P%TTg>{>R$1@Y(WTv9`~Z?Zu&Pg zpe*D4m2E0k&|E~9xxan3JH-Za16S$RGt`C#iVCTLmxv~5;ypLO?7C4bS#)4f&yRev zB7p_G->Kw;^roo5r1Dk$WkI0yKnIpr(DRQDi-H1eRCYxXdg$TNb-4dz;B$PKi4kWcZhJbQ;os2%Q`MgG9r$AlhL z3p2A2LQwJgSC!X?=m>8-Lyy=Fjz|s%f89M+)-+irSj8YK_v$GtbU(;QxIN|eCcuBs zQwMlI-hTDmfjImzV*Bv#>XXd_;?GCa|JfX*pL{5H@*FYYCme$6fpF^@(wPOh&ZhNERNy0hd7C2@ z8846I+onYbCbS<{@>`ln1?^H3yeQUq7A<=iJ?MKS`OlG_WkPr0 z$K#O*%+Y!SnTkE9{Rw6p|KjYcuTMQO_fkyHcl7Aq^4YUlm_+xheXc*JRX#@h4DOJA z68@pI$&$l96?xG_G`7W01M|eF`N?y=lmz^zKEbzF2%^+4mP=nB8d!L3#0BakxGPlV zgja;9vz}4MH2Ov{M5JDwJL#s3Z>#)m1V=sOBk5T8*Q29T!NKLrMWg(Q-2=Y z+c0*I9JUg>C(6z`ikxkSMCd5Mn$5mHe)}YIdfXjvv2w5jZW2A{X^--g_y>s#CeL8$yT3#;=Ug4w%L%dCG+74KnbG-Y&zW|T1L0A2&2YD zvW-D$1#6&F+|ros^v1H~xwf6%->s|RJo87yGH7}mA6QH?UthSf;=Do9G9s&Q&1$Ki zbK65MQS8UI(fv*oc{?X~AJb_hFa790%`KJd4{y-Yx3DFq0($xCg_wEz6>%Q>{W8 zKbM%EC%Q)HmRC@^v9o1}%l;dLp)pEKr6c^(83jfEaB>U_Q%9THc9?f}hFV!FCLnoI zz~{!fpE7=S?L*$p?J$&2IPPrwJ1Cgy_DDZsZu=18>q`}mEYsMY#-?(!`rUgXWeQug z0o3+JMU|nIQZkav>r?!^Gy68>_#WKVsoKq91N6mDUVN7Vt1hpvl>T^KjE$Scq~_@~ zReW%B{5Of3?PTDiB6-WgwV%T9$cl*ENk$8Q8tsiiAOgLImfZtkW4Wz9{ze-4a46+! zr%54=7d&6oWtT8B6C&Pk0iVg7FJXILE#$Yd32;uohCMmt}`>t*EN-Jpt-yJ^VL)!^R@ zCQ+X%4e1X zD1&Rww$;`b`7bf<6^^ZHOgbOFc6m&B+ROu$iZEgl?gtD=^^!~VD5Ye}9HwcPg&uEI z*21&76cP94Bb8hWAxCJu^)|9K1c^OkT+t%smQ4KW#+{SP=1K z4)%aUY^xs+CKYtdoUoZJyiJH}Fp6HiGo-sEc#37vX;bGtkKhf2nlJhnRkfQV<&==QS)yj3Ns_;9^TJ)&il!3q^pN{($@sItxNu^b>>o7!<7Y%wn!rRP3RGqgs-+N7Eob|ZR?LO4C*t1i_3 zb#KWm4Y+ePOZ;eCeH*qEt94MK>N5AD=O;r(fc{mRIagjen(=`X`T37DeM4VAIK|lZ zjrx4I#PyrwC6Q9DT~Kk%`<{8CEL3ypj`ipk>Dbr_TeS(@k?us=n6bCC`EiHVZ=<6n zscI}MQyExGdvT^oP-xITlbz?~xV7Ny7<)R6nTpW6f40Bi*^r@r2BTJ#pPm(d=nZ*- z^&Y7s2L0Is4m>9t+>hePdt>-(DZM4^7x#_)Bi`%koX(K3(YfP6RKQUioVyP%*u0fF zEBSx|*5BcsnA(^T zys|%ad(Xze@3oCMBb?$%eu+?P)P{)m+xu7$*Tz~YW7;7F-q;;37>YSjI6H+7M$-tO z`o&5sa{W+GkH+EE6|%{yU}1s0yO2a}trf%QKae=y9fdGo833PT&)jt4rXY#jg0ZVr zYW4dAfL?qUWTnz5)GR$YV?y!|kS!BczsFh46=Na)kUnACl>~ zi2+ECyb8W-#jPx6`t8ODGTOGPolr0v4Q>27!>hY9!M_`Y)6<@CJ6S)u>zzORyXvyO zb3X2@f99waTe1>#nvc}l93Wx7@j#RmN+y>dm7+<%M*Yc>xs+cCeSXdNMCJ~SF&#|p z8GRXhR`m4*=UkF3BHN%pm%`I0xD&KCuEt_gcTjB`oFKt);yc6uu z171}L*q4ZU^rYCYI|eZ-mpL4ua~}~)d9>K(syaqie|bnbQ|-3OUE>hY=B!1jZZV>@ zy=16FTHl1%Q;v$XZlsRyS_gC(oNiJREFU!FLfkrbJ-shzAEI{@tpmc|Nz20eotKGn z{*)RmM>yuB)PeK&Oy-@kgqhuXIX4EdHu?^`5_#F>5dAlhFO$|Q^!wRt;$ev=?Gkz} z`fjlZo5MLk@7>WGFzIbYtj_)q-Q7&iI$*ZTiYTRNQ^>Lm zH+wK{v*}Zzw?M|_N|<@CAb3FX54E-3e;T48rQuU6O?8O_!H=K8mMV!7q$C+PHJq(p zM;Qx(D^drqJkqv{?+fHQ^^R>(x_}u})W@%Uw%2bfvt*m{b4yVQdN*s&A{yyO;oI8b zWj88@0s~S9wSVNRQi7t+AN++=2a7Dg3sU)s&FR5;8A)f_d?O#9{N_JKMNx4U9KZ&N1mDXUM zucpiLjwxe+haf{#k%N;IUJ62w)|NjJmi=NDkG4EUFyJ1otq4lRf{}6_y%FN|BQp`b z@i1?`CH!_KyzJf4y!#|Ij80hhDgt^vy^pFamgN;JN{DfaqNReAg-r$yFz?*|^L#Ya zm6WXzkGD#+a>?H**ui%&Y&1}nTca`kL;9tsJuJol*_qr@XFoqxzJv}YOY4o%9*jGu2iVN>~<2?bTSa#b`Nq}&W1 zKPo##|DibG(YEJJ^D-%IFy*6q&^zwE@NTmJ?RC4neHT9WH*LCRjD~_vk0cYf2sF`Z zZ3ks)*vBx;(B$7Zx-rZxL|Mtf)YZaaN|yJ$7G_*h6&ESSm1Q1o&%w z+!J3s2lfal^2CMFo4=*@KW5U6rzDFaO}apqgC4?=>w;f;sTAW?-)aVU)7}pQ>OZaC zyT}y_Sr}gH$%oNSA=TW(5?YkF>s3e8q@yY`cF#YU! z$`%YIq;?&1wPGbRRFgGh>cD3=G&IBt$cNZGub)?YYDWjOeW<-S0w~5gEZ~nJ5qDY^ z1~ihm-@XAd6I9br32~ZzbkirbIs_Byy6N3yPA`tv6Eqe4ql{A8hJ+++1aaFw_d;z) zxiz{&V$*x{YW%Wd&VlNat%4$UQVGE-X2bDWhP6l@(Wt!^> zT?3?I)7isS82c%ijA@8MP04ig}oH75k*HhcxPnMwn<6`;Jt*Dw1Voh6z*I~ z{R5~FfWB?-$oT~f2Ck*1r>2_5I`P``J5lOK(iniP&)4-#+{yVW1yj5hX0g4TASfMZ zeUtU^_MgWt6i?E2LBdtR{YV?uWQ#@)^LmlfnrXwGpWoOp0M>C_=xkTlliVh`6<(_%x;itWSPkgjmP{S;~UYTLVd%fvkGJ< z?y>5yLs_kyWb0tnq~4fR(EKca)`jc}g)-Z;Np*c1@Kq@8K^JT>K#}xLgv=%Q(7U(% znjI>L^2HyR6u8_JV7gtojn=Wu6oht3Z)rL%4e2{oY9Nw}nNcEU&L58*8*4D4W48y@ z`DBUT?1rlxp;U6v0~ut`7bQ&1p(mPO-tebzK_M5%3UE`Ijn#C(V*Gf=&aJQ_@%=<9LPJ!%k@tLX!qaUpkVA7cOJnc5^PT;c#X9Sg{< zp=*>|(0EG^&3a{~+0WwSnYw*Z@g+)HqCPdAhUZSkD-l5%Z$vFjkd8_2mV+jTa z3LEb#D53h5bLE^6q-b$hXq%d!V0WcU7jQ=FtL)&e0pR3zJ?p^m_1hOd8@(2XSm7QS zAPY0(RG-DYHqh0Kg945`6Rd@;6Xz9WcQ+p28gi5);n+=&{Wr0f)_LT6^k6zsl1A*K z&j3r=Y>%>?Gr6KX4WeZQlPz`))wCn^?=B0Qz84Wa9cXhs$a>tNEt{$F;L&7!eVDo8 zu#Am_ek*DyteEl~rtUpNsW|4u>JlOWeQpXwkp{1 zZRS`wo$&8q_E63ua_WFcxsOk=r-p%`myZBOrCodcxI}9E?MZluWWC}!dW0+92#G5t z^o$?Bi8zH{!We7C(SMHs_BSrgY1jvh*OTO-6FFG+JtE~aJ%aJB$dPKTr@jnSW>{qR z1k;)q$tJ}LkH5QXC)l{NshRft=;>F#W=+XY?9X&8>6qmE{qj6H?LoZ7?!`ZKgo$5Y zb#i=og%)|XQv zc(Y`KX}M8#qZU}gPypxsjcUku-Z~Cwdsw$$yn-t7ZkI(n5w0nvQM9(buzYOt%zPx(~L zMs?aDjC82sHEhtYoAdSFp=DMcgjhj&qEBq}S&<;C#;w@q;IIa_U{JAM3hC{$qo^$F z#vo|7!dM@wd$F zu5F-sOpvx9dpW#T1H^keRwJGKi3?+^&o!XbYxjwepwX?BS*Y?uC-Dr|95W0>PPvJ7 z-viy71> zpVo)G<~PiKPMvxk#H)U!v2mu<+9snrzws@F20%$b=CMcN1nFerjXS!vwgnyRiID;k zgV3){<)>=?`slx)JhK_`>6gCazrS&u=A$$uq5Iq V^1CaFCy(FMx~YHT(>2?O{|}Z=nBD*Y literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/Icons/api-map.png b/Projects/Superalgos/Icons/api-map.png new file mode 100644 index 0000000000000000000000000000000000000000..e2f785f0a1099014d39e1a869a775e9af2bbce1a GIT binary patch literal 17532 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 z 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 literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/Icons/api-path-parameter.png b/Projects/Superalgos/Icons/api-path-parameter.png new file mode 100644 index 0000000000000000000000000000000000000000..f13a9dc29a7d2ed85b6b2e91f0fdca8a5fb9f8c7 GIT binary patch literal 13511 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 literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/Icons/api-path-parameters.png b/Projects/Superalgos/Icons/api-path-parameters.png new file mode 100644 index 0000000000000000000000000000000000000000..66fb84571396182f309931b9814b8d0d84cd0cb3 GIT binary patch literal 13313 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 literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/Icons/api-query-parameter.png b/Projects/Superalgos/Icons/api-query-parameter.png new file mode 100644 index 0000000000000000000000000000000000000000..d573c891d1743fd44958275553e6efe196ff402a GIT binary patch literal 9747 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 DFv)7J literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/Icons/api-query-responses.png b/Projects/Superalgos/Icons/api-query-responses.png new file mode 100644 index 0000000000000000000000000000000000000000..e028f221881a093b1179b35dbd4a91eb06188070 GIT binary patch literal 18798 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¦L1hEL_HLAUco=O`66f0WyZqpjEu(ZeLx<6C8}lU^cZZ z$+*WXvw9>p&)iyxgry4saGn2DAwFrY58kc-eBM%xzFXT*5!ga;bpNcj!}&>d07~k^6N~CHS&*%F zKi*C>eK0?#BS;>H>{3s=ErhpnQ}BkXSST3Ub8jOC@+r0cQ*V>4h7lV&ub07aHSp zYP7yb?RaqxltRodA>{5;%A4e|R|%iA?RP|UCJW(80r9ip4#it!wG`=It8LWhHPetU z96F?A!b&(RuO^FGDF|JNcyoJV>a(_e3D@S>xl7eq*LKz7T+P;6haYPm23*4q@^9+2 zl%#|Zpyjj}%_>un#H(A!jV5C)J-D26X(qa54(O@HRzh!BrkrS&s$E~XZS~sdTFoK{;;nCodB9*l_MpS(Viv-&o z#XoEr&y;5yw~lCT=*x}TvZksErYF81OTO%;7|Go5TFPHq71X%et}!k6J)*YC3TNny z&ofG2UD47PN&}m_I2K*F*!oI?W3{TU2Z;GWXP0Vz!Vig&HYtCa9GK9zQ>nEz*Ch}t zI4c@w?mHESytklm8;Qb(5RT_O430T8dO&W4VShBcO_=E1U~Q2ZD} zCPBD}WO={zuAM+7$YQKCH(EGgHnt2^@JdX%wSIRctLNnp*v#X-zc3PHK{o*}_;Pa4 zej9o3(^yuj6yVw|_K;i_;tU8XG8ip%Dor@j8%Q~zubNs+>l7;i#B+6Y(bf%@tsxta zFP}q{Z4F**$CAX2G8ZDAewYdn(;6D``FTzNwBF@NhmThIb^q$hk+ydA%P1Ul;_k;H zld<#kfq&09t|1m-bv@koY%46E|MjdqK^0{Q+E$t+ R^VcOWdboHw*E$}{_!kK;BZ2?` literal 0 HcmV?d00001 diff --git a/Projects/Superalgos/Icons/api-version.png b/Projects/Superalgos/Icons/api-version.png new file mode 100644 index 0000000000000000000000000000000000000000..232022e93145292f35dfaefb6cc4cb95032ab4e2 GIT binary patch literal 14640 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 H5B getContextVariables -> reportKey = " + reportKey) + detectWhereTheMarketBegins() + detectWhereTheMarketBegins() + getOwnStatusReport() - statusReport = statusDependencies.statusReports.get(reportKey); + function detectWhereTheMarketBegins() { + /* + We look first for Status Report that will tell us when the market starts. + */ + statusReport = statusDependencies.reportsByMainUtility.get('Market Starting Point'); - if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); - return - } - - if (statusReport.status === "Status Report is corrupt.") { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); - return - } - - thisReport = statusDependencies.statusReports.get(reportKey).file; - - if (thisReport.beginingOfMarket === undefined) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> It is too early too run this process since the trade history of the market is not there yet."); - - let customOK = { - result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, - message: "Dependency does not exist." + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + return } - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> customOK = " + customOK.message); - callBackFunction(customOK) - return - } - contextVariables.datetimeBeginingOfMarketFile = new Date( - thisReport.beginingOfMarket.year + "-" + - thisReport.beginingOfMarket.month + "-" + - thisReport.beginingOfMarket.days + " " + - thisReport.beginingOfMarket.hours + ":" + - thisReport.beginingOfMarket.minutes + - TS.projects.superalgos.globals.timeConstants.GMT_SECONDS); - - /* Second, we get the report from Exchange Raw Data, to know when the marted ends. */ - reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> getContextVariables -> reportKey = " + reportKey) - - statusReport = statusDependencies.statusReports.get(reportKey); - - if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); - return; - } - - if (statusReport.status === "Status Report is corrupt.") { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); - return; - } - - thisReport = statusDependencies.statusReports.get(reportKey).file; - - if (thisReport.lastFile === undefined) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); - - let customOK = { - result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, - message: "Dependency not ready." + if (statusReport.status === "Status Report is corrupt.") { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + return } - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> customOK = " + customOK.message); - callBackFunction(customOK); - return; + + thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.beginingOfMarket === undefined) { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[HINT] start -> getContextVariables -> It is too early too run this process since the trade history of the market is not there yet."); + + let customOK = { + result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, + message: "Dependency does not exist." + } + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + callBackFunction(customOK) + return + } + + contextVariables.datetimeBeginingOfMarketFile = new Date( + thisReport.beginingOfMarket.year + "-" + + thisReport.beginingOfMarket.month + "-" + + thisReport.beginingOfMarket.days + " " + + thisReport.beginingOfMarket.hours + ":" + + thisReport.beginingOfMarket.minutes + + TS.projects.superalgos.globals.timeConstants.GMT_SECONDS) } - contextVariables.datetimeLastAvailableDependencyFile = new Date( - thisReport.lastFile.year + "-" + - thisReport.lastFile.month + "-" + - thisReport.lastFile.days + " " + "00:00" + - TS.projects.superalgos.globals.timeConstants.GMT_SECONDS); + function detectWhereTheMarketBegins() { + /* + Second, we get the report from Exchange Raw Data, to know when the marted ends. + */ + statusReport = statusDependencies.reportsByMainUtility.get('Market Ending Point') - /* Finally we get our own Status Report. */ - reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Market" - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> getContextVariables -> reportKey = " + reportKey) + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + return; + } - statusReport = statusDependencies.statusReports.get(reportKey); + if (statusReport.status === "Status Report is corrupt.") { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + return; + } - if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); - return + thisReport = statusDependencies.statusReports.get(reportKey).file; + + if (thisReport.lastFile === undefined) { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + + let customOK = { + result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, + message: "Dependency not ready." + } + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + callBackFunction(customOK); + return; + } + + contextVariables.datetimeLastAvailableDependencyFile = new Date( + thisReport.lastFile.year + "-" + + thisReport.lastFile.month + "-" + + thisReport.lastFile.days + " " + "00:00" + + TS.projects.superalgos.globals.timeConstants.GMT_SECONDS) } - if (statusReport.status === "Status Report is corrupt.") { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process."); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); - return - } + function getOwnStatusReport() { + /* + Finally we get our own Status Report. + */ + statusReport = statusDependencies.reportsByMainUtility.get('Self Reference') - thisReport = statusDependencies.statusReports.get(reportKey).file; + if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + return + } + + if (statusReport.status === "Status Report is corrupt.") { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process."); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + return + } + + thisReport = statusDependencies.statusReports.get(reportKey).file + } if (thisReport.lastFile !== undefined) { + /* + We get in here when the report already exists, meaning that this process + has succesfully ran before at least once. + */ TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Process Running not for the very first time. -> reportKey = " + reportKey); @@ -225,9 +233,13 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process */ contextVariables.datetimeLastProducedFile = new Date(contextVariables.datetimeLastProducedFile.valueOf() - TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); - findPreviousContent() + loadExistingFiles() return } else { + /* + We get in here when the report does not exist, meaning that this process + has never ran succesfully before at least once. + */ TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Process Running for the very first time. -> reportKey = " + reportKey); @@ -265,7 +277,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } - function findPreviousContent() { + function loadExistingFiles() { /* This is where we read the current files we have produced at previous runs of this same process. We just read all the content and organize it @@ -281,7 +293,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process function loopBody() { let timeFrame = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][1]; TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> findPreviousContent -> loopBody -> timeFrame = " + timeFrame) + "[INFO] start -> loadExistingFiles -> loopBody -> timeFrame = " + timeFrame) let previousElements @@ -300,7 +312,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process fileStorage.getTextFile(filePath, onFileReceived); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> findPreviousContent -> loopBody -> getCandles -> getting file."); + "[INFO] start -> loadExistingFiles -> loopBody -> getCandles -> getting file."); function onFileReceived(err, text) { let dailyFile @@ -315,18 +327,18 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getCandles -> onFileReceived -> fileName = " + fileName); + "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> fileName = " + fileName); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getCandles -> onFileReceived -> filePath = " + filePath); + "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> filePath = " + filePath); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getCandles -> onFileReceived -> err = " + err.stack); + "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> err = " + err.stack); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getCandles -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); + "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); } } else { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> loopBody -> getCandles -> onFileReceived -> err = " + err.stack); + "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> err = " + err.stack); callBackFunction(err); } } @@ -345,7 +357,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> findPreviousContent -> err = " + err.stack); + "[ERROR] start -> loadExistingFiles -> err = " + err.stack); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/IndicatorOutput.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/IndicatorOutput.js index e53131f2c..52a3464af 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/IndicatorOutput.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/IndicatorOutput.js @@ -1,5 +1,9 @@ exports.newSuperalgosBotModulesIndicatorOutput = function (processIndex) { - const MODULE_NAME = "Indicator Bot"; + /* + This module coordinates the actions to be taken to generate an indicator output. + It is used from both Multi-Period-Market and Multi-Period-Daily frameworks. + */ + const MODULE_NAME = "Indicator Output"; let thisObject = { initialize: initialize, @@ -20,13 +24,20 @@ } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } - function start(dataFiles, timeFrame, timeFrameLabel, currentDay, interExecutionMemory, callBackFunction) { + function start( + dataFiles, + timeFrame, + timeFrameLabel, + currentDay, + interExecutionMemory, + callBackFunction + ) { try { @@ -43,13 +54,13 @@ /* The first phase here is about checking that we have everything we need at the definition level. */ let dataDependencies = TS.projects.superalgos.utilities.nodeFunctions.nodeBranchToArray( TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processDependencies, 'Data Dependency' - ) + ) if (TS.projects.superalgos.functionLibraries.singleMarketFunctions.validateDataDependencies(processIndex, dataDependencies, callBackFunction) !== true) { return } - let outputDatasets = TS.projects.superalgos.utilities.nodeFunctions.nodeBranchToArray ( + let outputDatasets = TS.projects.superalgos.utilities.nodeFunctions.nodeBranchToArray( TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset' - ) + ) if (TS.projects.superalgos.functionLibraries.singleMarketFunctions.validateOutputDatasets(processIndex, outputDatasets, callBackFunction) !== true) { return } /* The second phase is about transforming the inputs into a format that can be used to apply the user defined code. */ @@ -82,7 +93,7 @@ } /* Build the data */ - jsonData = TS.projects.superalgos.functionLibraries.singleMarketFunctions.dataBuildingProcedure(processIndex, + jsonData = TS.projects.superalgos.functionLibraries.singleMarketFunctions.dataBuildingProcedure(processIndex, products, mainDependency, recordDefinition, From 1b421bfec75cb11ef600384f2eb725fdc94afab1 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 18 May 2021 21:11:30 +0200 Subject: [PATCH 05/12] loadExistingFiles function implemented --- .../FromOneMinToMultiPeriodMarket.js | 68 ++++++++++++++----- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index af001ee09..a58419ca7 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -24,8 +24,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process and then it will process that full day again adding all the elements found at the current run. */ const MODULE_NAME = "From One Min To Multi Period Market" - const DEPENDENCY_FOLDER_NAME = "Candles" - const DEPENDENCY_ONE_MIN = "One-Min" + const ONE_MIN_DATASET_TYPE = "One-Min" let thisObject = { initialize: initialize, @@ -38,6 +37,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let statusDependencies let dataDependenciesModule let beginingOfMarket + let dataDependencyNode + let outputDatasetNode return thisObject; @@ -45,6 +46,38 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process statusDependencies = pStatusDependencies dataDependenciesModule = pDataDependencies + /* + This Framework have a few contraints that we are going to check right here. + One of them is the fact that it can only accept one data dependency. The + reason why is because the purpose of this framwork is to produce a transformation + between one dataset type (One-Min) to another dataset type (Multi-Period-Market). + To do that it can only handle one dependency and it will only produce one output. + + If the user has defined more than one data dependency or more than one output, we + are going to stop right here so that the user gets the message that this framework + is not to merge information and splitted into multiple outputs. + */ + if (dataDependenciesModule.curatedDependencyNodeArray.length > 0) { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[ERROR] initialize -> Validation Check Not Passed -> Expecting only one Data Dependency. Found = " + dataDependenciesModule.curatedDependencyNodeArray.length); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) + return + } else { + dataDependencyNode = dataDependenciesModule.curatedDependencyNodeArray[0] + } + + let outputDatasets = TS.projects.superalgos.utilities.nodeFunctions.nodeBranchToArray( + TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset' + ) + + if (outputDatasets.length > 0) { + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, + "[ERROR] initialize -> Validation Check Not Passed -> Expecting only one Output Dataset. Found = " + outputDatasets.length); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) + return + } else { + outputDatasetNode = outputDatasets[0] + } callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE) } @@ -54,6 +87,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process statusDependencies = undefined dataDependenciesModule = undefined thisObject = undefined + dataDependencyNode = undefined + outputDatasetNode = undefined } function start(callBackFunction) { @@ -284,9 +319,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process in arrays and keep them in memory. */ try { - let n = 0 // loop Variable representing each possible period as defined at the periods array. - - let allPreviousElements = [] // Each item of this array is an array of elements for a certain time frame + let n = 0 // loop Variable representing each possible time frame as defined at the time frames array. + let allPreviousElements = [] // Each item of this array is an array of elements for a certain time frame loopBody() @@ -297,14 +331,14 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let previousElements - getCandles() + readExistingFile() - function getCandles() { + function readExistingFile() { let fileName = 'Data.json'; let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + "/Output/" + - DEPENDENCY_FOLDER_NAME + "/" + + outputDatasetNode.referenceParent.parentNode.config.codeName + "/" + // Product Name TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName + "/" + timeFrame; filePath += '/' + fileName @@ -312,7 +346,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process fileStorage.getTextFile(filePath, onFileReceived); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> loadExistingFiles -> loopBody -> getCandles -> getting file."); + "[INFO] start -> loadExistingFiles -> loopBody -> readExistingFile -> getting file."); function onFileReceived(err, text) { let dailyFile @@ -323,22 +357,22 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process previousElements = dailyFile; allPreviousElements.push(previousElements); - controlLoop(); + controlLoop() } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> fileName = " + fileName); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> fileName = " + fileName); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> filePath = " + filePath); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> filePath = " + filePath); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> err = " + err.stack); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> err = " + err.stack); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); } } else { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> getCandles -> onFileReceived -> err = " + err.stack); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> err = " + err.stack); callBackFunction(err); } } @@ -489,7 +523,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process "Exchange-Raw-Data" + '/' + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + "/" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "-" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName - let filePath = filePathRoot + "/Output/" + DEPENDENCY_FOLDER_NAME + '/' + DEPENDENCY_ONE_MIN + '/' + dateForPath; + let filePath = filePathRoot + "/Output/" + dataDependencyNode.referenceParent.parentNode.config.codeName + '/' + ONE_MIN_DATASET_TYPE + '/' + dateForPath; filePath += '/' + fileName fileStorage.getTextFile(filePath, onFileReceived); @@ -646,7 +680,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let fileName = 'Data.json'; let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + "/Output/" + - DEPENDENCY_FOLDER_NAME + "/" + + outputDatasetNode.referenceParent.parentNode.config.codeName + "/" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName + "/" + timeFrame filePath += '/' + fileName From 35164873c2fb1c65ad42b441f9b3f22748d5b1f4 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 18 May 2021 23:36:17 +0200 Subject: [PATCH 06/12] Aggregation Function semi implemented --- .../FromOneMinToMultiPeriodMarket.js | 200 +++++++++++++----- 1 file changed, 145 insertions(+), 55 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index a58419ca7..f6b2ec990 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -37,7 +37,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let statusDependencies let dataDependenciesModule let beginingOfMarket - let dataDependencyNode + let dataDependencyNode let outputDatasetNode return thisObject; @@ -407,9 +407,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let outputElements = []; for (let n = 0; n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length; n++) { - const emptyArray1 = []; - const emptyArray2 = []; - outputElements.push(emptyArray1); + const emptyArray = [] + outputElements.push(emptyArray) } advanceTime() @@ -421,18 +420,27 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process date and then adding again all the elements found right now at that date and then from there into the future. */ - contextVariables.datetimeLastProducedFile = new Date(contextVariables.datetimeLastProducedFile.valueOf() + TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); + contextVariables.datetimeLastProducedFile = new Date(contextVariables.datetimeLastProducedFile.valueOf() + TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildOutput -> advanceTime -> New processing time @ " + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") + "[INFO] start -> buildOutput -> advanceTime -> New processing time @ " + + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") /* Validation that we are not going past the head of the market. */ if (contextVariables.datetimeLastProducedFile.valueOf() > contextVariables.datetimeLastAvailableDependencyFile.valueOf()) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildOutput -> advanceTime -> Head of the market found @ " + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") + "[INFO] start -> buildOutput -> advanceTime -> Head of the market found @ " + + contextVariables.datetimeLastProducedFile.getUTCFullYear() + "/" + + (contextVariables.datetimeLastProducedFile.getUTCMonth() + 1) + "/" + + contextVariables.datetimeLastProducedFile.getUTCDate() + ".") - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE); // Here is where we finish processing and wait for the platform to run this module again. + /* + Here is where we finish processing and wait for the bot to run this module again. + */ + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE) return } @@ -446,7 +454,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process TS.projects.superalgos.functionLibraries.processFunctions.processHeartBeat(processIndex, currentDateString, percentage) if (TS.projects.superalgos.utilities.dateTimeFunctions.areTheseDatesEqual(currentDate, new Date()) === false) { - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.newInternalLoop(currentDate, percentage); + TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.newInternalLoop(currentDate, percentage) } timeframesLoop() } @@ -466,8 +474,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process previousElements = allPreviousElements[n]; } - const outputPeriod = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][0]; - const timeFrame = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][1]; + const timeFrameLabel = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][0] + const timeFrame = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][1] /* Here we are inside a Loop that is going to advance 1 day at the time, at each pass, we will read one of Exchange Raw Data's daily files and @@ -484,13 +492,11 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process */ if (previousElements !== undefined && previousElements.length !== 0) { for (let i = 0; i < previousElements.length; i++) { - let element = { - open: previousElements[i][2], - close: previousElements[i][3], - min: previousElements[i][0], - max: previousElements[i][1], - begin: previousElements[i][4], - end: previousElements[i][5] + let element = {} + + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + element[property.config.codeName] = record[j] } if (element.end < contextVariables.datetimeLastProducedFile.valueOf()) { @@ -503,8 +509,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process allPreviousElements[n] = [] // erasing these so as not to duplicate them. } /* - From here on is where every iteration of the loop fully runs. Here is where we - read Exchange Raw Data's files and add their content to whatever + From here on is where every iteration of the loop fully runs. + Here is where we read Data Depnedency's files and add their content to whatever we already have in our arrays in-memory. In this way the process will run as many days needed and it should only stop when it reaches the head of the market. @@ -512,7 +518,10 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process nextDailyFile(); function nextDailyFile() { - let dateForPath = contextVariables.datetimeLastProducedFile.getUTCFullYear() + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCMonth() + 1, 2) + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2); + let dateForPath = contextVariables.datetimeLastProducedFile.getUTCFullYear() + '/' + + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCMonth() + 1, 2) + '/' + + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2); + let fileName = "Data.json" let filePathRoot = @@ -520,9 +529,11 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process TS.projects.superalgos.globals.taskConstants.PROJECT_DEFINITION_NODE.config.codeName + "/" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.type.replace(' ', '-') + "/" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName + "/" + - "Exchange-Raw-Data" + '/' + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + "/" + + dataDependencyNode.referenceParent.parentNode.config.codeName + '/' + + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + "/" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "-" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName + let filePath = filePathRoot + "/Output/" + dataDependencyNode.referenceParent.parentNode.config.codeName + '/' + ONE_MIN_DATASET_TYPE + '/' + dateForPath; filePath += '/' + fileName @@ -565,55 +576,134 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } - const inputElementPerdiod = 60 * 1000; // 1 min const inputFilePeriod = 24 * 60 * 60 * 1000; // 24 hs - let totaloutputElements = inputFilePeriod / outputPeriod; // this should be 2 in this case. + let totalOutputElements = inputFilePeriod / timeFrameLabel; // this should be 2 in this case. let beginingOutputTime = contextVariables.datetimeLastProducedFile.valueOf(); /* - The algorithm that follows is going to agregate elements of 1 min timeFrame read from Exchange Raw Data, into elements of each timeFrame - that Candles Volumes generates. For market files those timePediods goes from 1h to 24hs. + The algorithm that follows is going to agregate elements of 1 min timeFrame + read from Data Dependency File, into elements of each timeFrame. */ - for (let i = 0; i < totaloutputElements; i++) { + for (let i = 0; i < totalOutputElements; i++) { - let outputElement = { - open: 0, - close: 0, - min: 0, - max: 0, - begin: 0, - end: 0 - }; + let saveElement = false + /* + Initialize the outputElement object. + */ + let outputElement = {} - let saveElement = false; - outputElement.begin = beginingOutputTime + i * outputPeriod; - outputElement.end = beginingOutputTime + (i + 1) * outputPeriod - 1; + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + + if (property.config.isString === true || property.config.isDate === true) { + outputElement[property.config.codeName] = "" // Default Value + } else { + outputElement[property.config.codeName] = 0 // Default Value + } + if (property.config.isBoolean === true) { + outputElement[property.config.codeName] = false // Default Value + } + } + + /* + Setting the begin and end for this element. + */ + outputElement.begin = beginingOutputTime + i * timeFrameLabel; + outputElement.end = beginingOutputTime + (i + 1) * timeFrameLabel - 1; for (let j = 0; j < dailyFile.length; j++) { - let element = { - open: dailyFile[j][2], - close: dailyFile[j][3], - min: dailyFile[j][0], - max: dailyFile[j][1], - begin: dailyFile[j][4], - end: dailyFile[j][5] + let element = {} + let record = {} + + record.values = dailyFile[j] + record.map = new Map() + + /* + Set up the Data Dependency Record Map and Data Dependency Element Object + */ + for (let k = 0; k < dataDependencyNode.referenceParent.parentNode.record.properties.length; k++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[k] + record.map.set(property.config.codeName, record.values[k]) + element[property.config.codeName] = record.values[k] + } + /* + Here we discard all the elements out of range based on the begin and end properties of + the Data Dependency element. + */ + if ( + element.begin !== undefined && + element.end !== undefined && + element.begin >= outputElement.begin && + element.end <= outputElement.end) { + aggregateElements() } - /* Here we discard all the elements out of range. */ - if (element.begin >= outputElement.begin && element.end <= outputElement.end) { - if (saveElement === false) { // this will set the value only once. - outputElement.open = element.open; - outputElement.min = element.min; - outputElement.max = element.max; + /* + Here we discard all the elements out of range based on the timestamp propertiy of + the Data Dependency element. + */ + if ( + element.timestamp !== undefined && + element.timestamp >= outputElement.begin && + element.timestamp <= outputElement.end) { + aggregateElements() + } + + function aggregateElements() { + aggregationMethodFirst() + saveElement = true + aggregationMethodLast() + + function aggregationMethodFirst() { + /* + Here we process the FIRST type of aggregation. + */ + if (saveElement === false) { + + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + if (property.config.aggregationMethod === 'First') { + outputElement[property.config.codeName] = record.map.get(property.config.codeName) + } + } + } } - saveElement = true; - outputElement.close = element.close; // only the last one will be saved + + function aggregationMethodLast() { + /* + This is the LAST type of aggregation. + + Everything that follows will be set for each element overiding the previous + ones, so only the last values will survive. + */ + + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + if (property.config.aggregationMethod === 'Last') { + outputElement[property.config.codeName] = record.map.get(property.config.codeName) + } + } + } + + + + /* Here we process the MIN type of aggregation */ if (element.min < outputElement.min) { - outputElement.min = element.min; + outputElement.min = element.min } + + /* Here we process the MAX type of aggregation */ if (element.max > outputElement.max) { - outputElement.max = element.max; + outputElement.max = element.max } + + /* Here we process the SUM type of aggregation */ + + + /* Here we process the AVG type of agregation */ + + + } } if (saveElement === true) { // then we have a valid element, otherwise it means there were no elements to fill this one in its time range. From 30644ff9e4e3bd5b2a0b5f881846ee55c1190358 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 18 May 2021 23:58:50 +0200 Subject: [PATCH 07/12] Aggregation Functions fully implemented --- .../FromOneMinToMultiPeriodMarket.js | 76 +++++++++++++++---- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index f6b2ec990..07286cf29 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -589,7 +589,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process /* Initialize the outputElement object. */ - let outputElement = {} + let outputElement = {} // This will be the object that we will eventually save. + let outputElementAverage = {} // We will use this object to help us aggregate values by calculating an average. for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] @@ -649,9 +650,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } function aggregateElements() { + aggregationMethodFirst() - saveElement = true aggregationMethodLast() + aggregationMethodMin() + aggregationMethodMax() + aggregationMethodSum() + aggregationMethodAvg() + + saveElement = true function aggregationMethodFirst() { /* @@ -668,7 +675,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } - function aggregationMethodLast() { /* This is the LAST type of aggregation. @@ -685,25 +691,69 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } + function aggregationMethodMin() { + /* + This is the MIN type of aggregation. - - /* Here we process the MIN type of aggregation */ - if (element.min < outputElement.min) { - outputElement.min = element.min + Note that to be able to calculate the minimum, we will be assigning to all properties the first + element values, so as to have a baseline from where to compare later on. + */ + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + if (property.config.aggregationMethod === 'Min' || saveElement === false) { + if (record.map.get(property.config.codeName) < outputElement[property.config.codeName]) { + outputElement[property.config.codeName] = record.map.get(property.config.codeName) + } + } + } } - /* Here we process the MAX type of aggregation */ - if (element.max > outputElement.max) { - outputElement.max = element.max + function aggregationMethodMax() { + /* + This is the MAX type of aggregation. + */ + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + if (property.config.aggregationMethod === 'Max') { + if (record.map.get(property.config.codeName) > outputElement[property.config.codeName]) { + outputElement[property.config.codeName] = record.map.get(property.config.codeName) + } + } + } } - /* Here we process the SUM type of aggregation */ + function aggregationMethodSum() { + /* + This is the SUM type of aggregation. + */ + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + if (property.config.aggregationMethod === 'Sum') { + outputElement[property.config.codeName] = outputElement[property.config.codeName] + record.map.get(property.config.codeName) + } + } + } + function aggregationMethodAvg() { + /* + This is the AVG type of aggregation. + */ + for (let j = 0; j < outputDatasetNode.referenceParent.parentNode.record.properties.length; j++) { + let property = outputDatasetNode.referenceParent.parentNode.record.properties[j] + if (property.config.aggregationMethod === 'Average') { - /* Here we process the AVG type of agregation */ - + if (outputElementAverage[property.config.codeName] === undefined) { + outputElementAverage[property.config.codeName].sum = 0 + outputElementAverage[property.config.codeName].count = 0 + } + outputElementAverage[property.config.codeName].sum = outputElementAverage[property.config.codeName].sum + record.map.get(property.config.codeName) + outputElementAverage[property.config.codeName].count = outputElementAverage[property.config.codeName].count + 1 + outputElement[property.config.codeName] = outputElementAverage[property.config.codeName].sum / outputElementAverage[property.config.codeName].count + } + } + } } } if (saveElement === true) { // then we have a valid element, otherwise it means there were no elements to fill this one in its time range. From 098843221f6d80a0c3e06671c908bff1f711ee78 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 19 May 2021 16:35:15 +0200 Subject: [PATCH 08/12] Updated Icons --- .../nodes/api-path-parameters.svg | 4 ++-- .../Icons-SVG-Sources/nodes/api-version.svg | 12 +++++++----- .../Superalgos/Icons/api-path-parameters.png | Bin 13313 -> 13360 bytes Projects/Superalgos/Icons/api-version.png | Bin 14640 -> 14139 bytes 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg index 70c99224b..bc1534aca 100644 --- a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-path-parameters.svg @@ -7,8 +7,8 @@ - - + + diff --git a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg index 76e1734df..2667e8d67 100644 --- a/Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg +++ b/Projects/Superalgos/Icons-SVG-Sources/nodes/api-version.svg @@ -1,10 +1,12 @@ - - - - - + + + + + + + diff --git a/Projects/Superalgos/Icons/api-path-parameters.png b/Projects/Superalgos/Icons/api-path-parameters.png index 66fb84571396182f309931b9814b8d0d84cd0cb3..75e29f90207d8bdefa3d687b4f80c266c651e635 100644 GIT binary patch literal 13360 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 diff --git a/Projects/Superalgos/Icons/api-version.png b/Projects/Superalgos/Icons/api-version.png index 232022e93145292f35dfaefb6cc4cb95032ab4e2..3ee1cd519850b7c9d9cf2741db386d2b80341095 100644 GIT binary patch literal 14139 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 literal 14640 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 H5B Date: Wed, 19 May 2021 17:29:11 +0200 Subject: [PATCH 09/12] docs improvements: buttons for User Manual, Data Mines and Reviews --- .../Superalgos/Schemas/Docs-Books/reviews.json | 14 ++++++++++++++ ...=> users-formula-and-code-examples - Copy.json} | 0 ...eat-project-with-an-even-greater-potential.json | 2 +- Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js | 6 ++++++ 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 Projects/Superalgos/Schemas/Docs-Books/reviews.json rename Projects/Superalgos/Schemas/Docs-Books/{users-formula-and-code-examples.json => users-formula-and-code-examples - Copy.json} (100%) diff --git a/Projects/Superalgos/Schemas/Docs-Books/reviews.json b/Projects/Superalgos/Schemas/Docs-Books/reviews.json new file mode 100644 index 000000000..3715a8c10 --- /dev/null +++ b/Projects/Superalgos/Schemas/Docs-Books/reviews.json @@ -0,0 +1,14 @@ +{ + "type": "Reviews", + "definition": { + "text": "This book is a cataloge of all types of reviews at the Docs.", + "updated": 1621437863554 + }, + "paragraphs": [ + { + "style": "Chapter", + "text": "I->Superalgos->Review->Superalgos Project Review->These are reviews of the project submited by users.", + "updated": 1621437834465 + } + ] +} \ No newline at end of file diff --git a/Projects/Superalgos/Schemas/Docs-Books/users-formula-and-code-examples.json b/Projects/Superalgos/Schemas/Docs-Books/users-formula-and-code-examples - Copy.json similarity index 100% rename from Projects/Superalgos/Schemas/Docs-Books/users-formula-and-code-examples.json rename to Projects/Superalgos/Schemas/Docs-Books/users-formula-and-code-examples - Copy.json diff --git a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-002-superalgos-review-a-great-project-with-an-even-greater-potential.json b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-002-superalgos-review-a-great-project-with-an-even-greater-potential.json index 81cfcde6f..02da69837 100644 --- a/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-002-superalgos-review-a-great-project-with-an-even-greater-potential.json +++ b/Projects/Superalgos/Schemas/Docs-Reviews/superalgos-project-review-002-superalgos-review-a-great-project-with-an-even-greater-potential.json @@ -1,7 +1,7 @@ { "review": "Superalgos Project Review", "pageNumber": 2, - "type": "Superalgos Review - A GREAT PROJECT WITH AN EVEN GREATER POTENTIAL", + "type": "Superalgos Review - A great project with an even greater potential", "definition": { "text": "Hello, I'm 0xperez and this is my Superalgos review!", "updated": 1614626208522 diff --git a/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js b/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js index 19187a0c5..ca269297e 100644 --- a/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js +++ b/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js @@ -38,6 +38,12 @@ function newSuperalgosDocsFooter() { if (UI.projects.superalgos.spaces.docsSpace.currentBookBeingRendered !== undefined) { HTML = HTML + '' } + + HTML = HTML + '' + HTML = HTML + '' + HTML = HTML + '' + HTML = HTML + '' + HTML = HTML + '' HTML = HTML + '' From a5928dc51d6f0ed0e340cd38d8f7381058749961 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 19 May 2021 18:02:03 +0200 Subject: [PATCH 10/12] Update Footer.js --- Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js b/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js index ca269297e..59404b1fe 100644 --- a/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js +++ b/Projects/Superalgos/UI/Spaces/Docs-Space/Footer.js @@ -211,6 +211,7 @@ function newSuperalgosDocsFooter() { HTML = HTML + '' HTML = HTML + '
  • UX/UI Design Group
  • ' HTML = HTML + '
  • Collaborations Group
  • ' + HTML = HTML + '
  • Codebase Learning Group
  • ' HTML = HTML + '
  • Hablemos en Español!
  • ' HTML = HTML + '
  • Говорим по русски!
  • ' HTML = HTML + '' @@ -221,7 +222,7 @@ function newSuperalgosDocsFooter() { HTML = HTML + '
      ' HTML = HTML + '
    • Official Announcements
    • ' HTML = HTML + '
    • Features and Functionality
    • ' - HTML = HTML + '
    • Main Repository
    • ' + HTML = HTML + '
    • Main Github Repository
    • ' HTML = HTML + '
    • Subscribe in YouTube
    • ' HTML = HTML + '
    • Follow us on Twitter
    • ' HTML = HTML + '
    • Connect on Facebook
    • ' From 5bd2f0c554ff32149303a682080b18e3d17dcba7 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 19 May 2021 18:23:30 +0200 Subject: [PATCH 11/12] API Data Fetcher DeepScan fixes --- .../FromOneMinToMultiPeriodMarket.js | 54 ++++++++----------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index 07286cf29..63e82c8f2 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -106,47 +106,46 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process function getContextVariables() { try { let thisReport - let reportKey let statusReport detectWhereTheMarketBegins() - detectWhereTheMarketBegins() + detectWhereTheMarketEnds() getOwnStatusReport() function detectWhereTheMarketBegins() { /* We look first for Status Report that will tell us when the market starts. */ - statusReport = statusDependencies.reportsByMainUtility.get('Market Starting Point'); + statusReport = statusDependencies.reportsByMainUtility.get('Market Starting Point') if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> Status Report does not exist. Retrying Later. "); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); return } if (statusReport.status === "Status Report is corrupt.") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + "[ERROR] start -> getContextVariables -> detectWhereTheMarketBegins-> Can not continue because dependecy Status Report is corrupt. "); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); return } - thisReport = statusDependencies.statusReports.get(reportKey).file; + thisReport = statusReport.file if (thisReport.beginingOfMarket === undefined) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> Undefined Last File. " + ); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> It is too early too run this process since the trade history of the market is not there yet."); + "[HINT] start -> getContextVariables -> detectWhereTheMarketBegins-> It is too early too run this process since the trade history of the market is not there yet."); let customOK = { result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, message: "Dependency does not exist." } TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> customOK = " + customOK.message); callBackFunction(customOK) return } @@ -160,7 +159,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process TS.projects.superalgos.globals.timeConstants.GMT_SECONDS) } - function detectWhereTheMarketBegins() { + function detectWhereTheMarketEnds() { /* Second, we get the report from Exchange Raw Data, to know when the marted ends. */ @@ -168,30 +167,30 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); + "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> Status Report does not exist. Retrying Later. "); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); return; } if (statusReport.status === "Status Report is corrupt.") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); + "[ERROR] start -> getContextVariables -> detectWhereTheMarketEnds-> Can not continue because dependecy Status Report is corrupt. "); callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); return; } - thisReport = statusDependencies.statusReports.get(reportKey).file; + thisReport = statusReport.file if (thisReport.lastFile === undefined) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey); + "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> Undefined Last File." ); let customOK = { result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, message: "Dependency not ready." } TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> customOK = " + customOK.message); + "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> customOK = " + customOK.message); callBackFunction(customOK); return; } @@ -223,7 +222,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process return } - thisReport = statusDependencies.statusReports.get(reportKey).file + thisReport = statusReport.file } if (thisReport.lastFile !== undefined) { @@ -231,14 +230,12 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process We get in here when the report already exists, meaning that this process has succesfully ran before at least once. */ - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> getContextVariables -> Process Running not for the very first time. -> reportKey = " + reportKey); beginingOfMarket = new Date(thisReport.beginingOfMarket); if (beginingOfMarket.valueOf() !== contextVariables.datetimeBeginingOfMarketFile.valueOf()) { // Reset Mechanism for Begining of the Market TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> getContextVariables -> Reset Mechanism for Begining of the Market Activated. -> reportKey = " + reportKey); + "[INFO] start -> getContextVariables -> getOwnStatusReport-> Reset Mechanism for Begining of the Market Activated." ); beginingOfMarket = new Date( contextVariables.datetimeBeginingOfMarketFile.getUTCFullYear() + "-" + @@ -259,7 +256,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } contextVariables.datetimeLastProducedFile = new Date(thisReport.lastFile); - /* Here we assume that the last day written might contain incomplete information. This actually happens every time the head of the market is reached. @@ -275,9 +271,6 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process We get in here when the report does not exist, meaning that this process has never ran succesfully before at least once. */ - TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> getContextVariables -> Process Running for the very first time. -> reportKey = " + reportKey); - beginingOfMarket = new Date( contextVariables.datetimeBeginingOfMarketFile.getUTCFullYear() + "-" + (contextVariables.datetimeBeginingOfMarketFile.getUTCMonth() + 1) + "-" + @@ -299,14 +292,14 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> err = " + err.stack); + "[ERROR] start -> getContextVariables -> getOwnStatusReport-> err = " + err.stack); if (err.message === "Cannot read property 'file' of undefined") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> Check the bot configuration to see if all of its statusDependencies declarations are correct. "); + "[HINT] start -> getContextVariables -> getOwnStatusReport-> Check the bot configuration to see if all of its statusDependencies declarations are correct. "); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)); + "[HINT] start -> getContextVariables -> getOwnStatusReport-> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)); TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> Dependencies loaded -> Double check that you are not running a process that only can be run at noTime mode at a certain month when it is not prepared to do so."); + "[HINT] start -> getContextVariables -> getOwnStatusReport-> Dependencies loaded -> Double check that you are not running a process that only can be run at noTime mode at a certain month when it is not prepared to do so."); } callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } @@ -809,8 +802,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let fileContent = "" for (let i = 0; i < elements.length; i++) { - let element = elements[i]; - fileContent = fileContent + separator + '[' + elements[i].min + "," + elements[i].max + "," + elements[i].open + "," + elements[i].close + "," + elements[i].begin + "," + elements[i].end + "]"; + let element = elements[i] + fileContent = fileContent + separator + '[' + element.min + "," + element.max + "," + element.open + "," + element.close + "," + element.begin + "," + element.end + "]" if (separator === "") { separator = ","; } fileRecordCounter++ } @@ -860,8 +853,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process "[INFO] start -> writeStatusReport -> lastFileDate = " + lastFileDate) try { - let reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Market" - let thisReport = statusDependencies.statusReports.get(reportKey) + let thisReport = statusDependencies.reportsByMainUtility.get('Self Reference') thisReport.file.lastExecution = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).PROCESS_DATETIME thisReport.file.lastFile = lastFileDate From 232b2ef63c9d4c262d1bd6d016dbff8fc542f340 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 19 May 2021 18:26:59 +0200 Subject: [PATCH 12/12] API Data Fetcher DeepScan more fixes --- .../FromOneMinToMultiPeriodMarket.js | 156 +++++++++--------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js index 63e82c8f2..1d403a015 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js +++ b/Projects/Superalgos/TS/Bot-Modules/Indicator-Bot/FromOneMinToMultiPeriodMarket.js @@ -59,7 +59,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process */ if (dataDependenciesModule.curatedDependencyNodeArray.length > 0) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] initialize -> Validation Check Not Passed -> Expecting only one Data Dependency. Found = " + dataDependenciesModule.curatedDependencyNodeArray.length); + "[ERROR] initialize -> Validation Check Not Passed -> Expecting only one Data Dependency. Found = " + dataDependenciesModule.curatedDependencyNodeArray.length) callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) return } else { @@ -72,7 +72,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (outputDatasets.length > 0) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] initialize -> Validation Check Not Passed -> Expecting only one Output Dataset. Found = " + outputDatasets.length); + "[ERROR] initialize -> Validation Check Not Passed -> Expecting only one Output Dataset. Found = " + outputDatasets.length) callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) return } else { @@ -101,7 +101,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process datetimeLastAvailableDependencyFile: undefined // Datetime of the last file available to be used as an input of this process. }; - getContextVariables(); + getContextVariables() function getContextVariables() { try { @@ -120,15 +120,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> Status Report does not exist. Retrying Later. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> Status Report does not exist. Retrying Later. ") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return } if (statusReport.status === "Status Report is corrupt.") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> detectWhereTheMarketBegins-> Can not continue because dependecy Status Report is corrupt. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[ERROR] start -> getContextVariables -> detectWhereTheMarketBegins-> Can not continue because dependecy Status Report is corrupt. ") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return } @@ -136,16 +136,16 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (thisReport.beginingOfMarket === undefined) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> Undefined Last File. " + ); + "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> Undefined Last File. " ) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> detectWhereTheMarketBegins-> It is too early too run this process since the trade history of the market is not there yet."); + "[HINT] start -> getContextVariables -> detectWhereTheMarketBegins-> It is too early too run this process since the trade history of the market is not there yet.") let customOK = { result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, message: "Dependency does not exist." } TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> customOK = " + customOK.message); + "[WARN] start -> getContextVariables -> detectWhereTheMarketBegins-> customOK = " + customOK.message) callBackFunction(customOK) return } @@ -167,15 +167,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> Status Report does not exist. Retrying Later. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> Status Report does not exist. Retrying Later. ") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return; } if (statusReport.status === "Status Report is corrupt.") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> detectWhereTheMarketEnds-> Can not continue because dependecy Status Report is corrupt. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[ERROR] start -> getContextVariables -> detectWhereTheMarketEnds-> Can not continue because dependecy Status Report is corrupt. ") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return; } @@ -183,15 +183,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (thisReport.lastFile === undefined) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> Undefined Last File." ); + "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> Undefined Last File." ) let customOK = { result: TS.projects.superalgos.globals.standardResponses.CUSTOM_OK_RESPONSE.result, message: "Dependency not ready." } TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> customOK = " + customOK.message); - callBackFunction(customOK); + "[WARN] start -> getContextVariables -> detectWhereTheMarketEnds-> customOK = " + customOK.message) + callBackFunction(customOK) return; } @@ -210,15 +210,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month. TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return } if (statusReport.status === "Status Report is corrupt.") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process."); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process.") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) return } @@ -231,38 +231,38 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process has succesfully ran before at least once. */ - beginingOfMarket = new Date(thisReport.beginingOfMarket); + beginingOfMarket = new Date(thisReport.beginingOfMarket) if (beginingOfMarket.valueOf() !== contextVariables.datetimeBeginingOfMarketFile.valueOf()) { // Reset Mechanism for Begining of the Market TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> getContextVariables -> getOwnStatusReport-> Reset Mechanism for Begining of the Market Activated." ); + "[INFO] start -> getContextVariables -> getOwnStatusReport-> Reset Mechanism for Begining of the Market Activated." ) beginingOfMarket = new Date( contextVariables.datetimeBeginingOfMarketFile.getUTCFullYear() + "-" + (contextVariables.datetimeBeginingOfMarketFile.getUTCMonth() + 1) + "-" + contextVariables.datetimeBeginingOfMarketFile.getUTCDate() + " " + "00:00" + - TS.projects.superalgos.globals.timeConstants.GMT_SECONDS); + TS.projects.superalgos.globals.timeConstants.GMT_SECONDS) contextVariables.datetimeLastProducedFile = new Date( contextVariables.datetimeBeginingOfMarketFile.getUTCFullYear() + "-" + (contextVariables.datetimeBeginingOfMarketFile.getUTCMonth() + 1) + "-" + contextVariables.datetimeBeginingOfMarketFile.getUTCDate() + " " + "00:00" + - TS.projects.superalgos.globals.timeConstants.GMT_SECONDS); + TS.projects.superalgos.globals.timeConstants.GMT_SECONDS) contextVariables.datetimeLastProducedFile = new Date( contextVariables.datetimeLastProducedFile.valueOf() - - TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); // Go back one day to start well. + TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS) // Go back one day to start well. buildOutput() return } - contextVariables.datetimeLastProducedFile = new Date(thisReport.lastFile); + contextVariables.datetimeLastProducedFile = new Date(thisReport.lastFile) /* Here we assume that the last day written might contain incomplete information. This actually happens every time the head of the market is reached. For that reason we go back one day, the partial information is discarded and added again with whatever new info is available. */ - contextVariables.datetimeLastProducedFile = new Date(contextVariables.datetimeLastProducedFile.valueOf() - TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); + contextVariables.datetimeLastProducedFile = new Date(contextVariables.datetimeLastProducedFile.valueOf() - TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS) loadExistingFiles() return @@ -275,15 +275,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process contextVariables.datetimeBeginingOfMarketFile.getUTCFullYear() + "-" + (contextVariables.datetimeBeginingOfMarketFile.getUTCMonth() + 1) + "-" + contextVariables.datetimeBeginingOfMarketFile.getUTCDate() + " " + "00:00" + - TS.projects.superalgos.globals.timeConstants.GMT_SECONDS); + TS.projects.superalgos.globals.timeConstants.GMT_SECONDS) contextVariables.datetimeLastProducedFile = new Date( contextVariables.datetimeBeginingOfMarketFile.getUTCFullYear() + "-" + (contextVariables.datetimeBeginingOfMarketFile.getUTCMonth() + 1) + "-" + contextVariables.datetimeBeginingOfMarketFile.getUTCDate() + " " + "00:00" + - TS.projects.superalgos.globals.timeConstants.GMT_SECONDS); + TS.projects.superalgos.globals.timeConstants.GMT_SECONDS) contextVariables.datetimeLastProducedFile = new Date( contextVariables.datetimeLastProducedFile.valueOf() - - TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS); // Go back one day to start well. + TS.projects.superalgos.globals.timeConstants.ONE_DAY_IN_MILISECONDS) // Go back one day to start well. buildOutput() return @@ -292,16 +292,16 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> getOwnStatusReport-> err = " + err.stack); + "[ERROR] start -> getContextVariables -> getOwnStatusReport-> err = " + err.stack) if (err.message === "Cannot read property 'file' of undefined") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> getOwnStatusReport-> Check the bot configuration to see if all of its statusDependencies declarations are correct. "); + "[HINT] start -> getContextVariables -> getOwnStatusReport-> Check the bot configuration to see if all of its statusDependencies declarations are correct. ") TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> getOwnStatusReport-> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)); + "[HINT] start -> getContextVariables -> getOwnStatusReport-> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> getOwnStatusReport-> Dependencies loaded -> Double check that you are not running a process that only can be run at noTime mode at a certain month when it is not prepared to do so."); + "[HINT] start -> getContextVariables -> getOwnStatusReport-> Dependencies loaded -> Double check that you are not running a process that only can be run at noTime mode at a certain month when it is not prepared to do so.") } - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } @@ -336,37 +336,37 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process timeFrame; filePath += '/' + fileName - fileStorage.getTextFile(filePath, onFileReceived); + fileStorage.getTextFile(filePath, onFileReceived) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> loadExistingFiles -> loopBody -> readExistingFile -> getting file."); + "[INFO] start -> loadExistingFiles -> loopBody -> readExistingFile -> getting file.") function onFileReceived(err, text) { let dailyFile if (err.result === TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { try { - dailyFile = JSON.parse(text); + dailyFile = JSON.parse(text) previousElements = dailyFile; - allPreviousElements.push(previousElements); + allPreviousElements.push(previousElements) controlLoop() } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> fileName = " + fileName); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> fileName = " + fileName) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> filePath = " + filePath); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> filePath = " + filePath) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> err = " + err.stack); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> err = " + err.stack) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry.") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) } } else { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> err = " + err.stack); - callBackFunction(err); + "[ERROR] start -> loadExistingFiles -> loopBody -> readExistingFile -> onFileReceived -> err = " + err.stack) + callBackFunction(err) } } } @@ -377,15 +377,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length) { loopBody() } else { - buildOutput(allPreviousElements); + buildOutput(allPreviousElements) } } } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> loadExistingFiles -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> loadExistingFiles -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } @@ -441,7 +441,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let currentDateString = contextVariables.datetimeLastProducedFile.getUTCFullYear() + '-' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCMonth() + 1, 2) + '-' + - TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2); + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2) let currentDate = new Date(contextVariables.datetimeLastProducedFile) let percentage = TS.projects.superalgos.utilities.dateTimeFunctions.getPercentage(fromDate, currentDate, lastDate) TS.projects.superalgos.functionLibraries.processFunctions.processHeartBeat(processIndex, currentDateString, percentage) @@ -493,7 +493,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } if (element.end < contextVariables.datetimeLastProducedFile.valueOf()) { - outputElements[n].push(element); + outputElements[n].push(element) } else { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] start -> buildOutput -> timeframesLoop -> loopBody -> Element # " + i + " @ " + timeFrame + " discarded for closing past the current process time.") @@ -508,12 +508,12 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process many days needed and it should only stop when it reaches the head of the market. */ - nextDailyFile(); + nextDailyFile() function nextDailyFile() { let dateForPath = contextVariables.datetimeLastProducedFile.getUTCFullYear() + '/' + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCMonth() + 1, 2) + '/' + - TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2); + TS.projects.superalgos.utilities.miscellaneousFunctions.pad(contextVariables.datetimeLastProducedFile.getUTCDate(), 2) let fileName = "Data.json" @@ -530,10 +530,10 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process let filePath = filePathRoot + "/Output/" + dataDependencyNode.referenceParent.parentNode.config.codeName + '/' + ONE_MIN_DATASET_TYPE + '/' + dateForPath; filePath += '/' + fileName - fileStorage.getTextFile(filePath, onFileReceived); + fileStorage.getTextFile(filePath, onFileReceived) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> getting file at dateForPath = " + dateForPath); + "[INFO] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> getting file at dateForPath = " + dateForPath) function onFileReceived(err, text) { try { @@ -541,13 +541,13 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (err.result === TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { try { - dailyFile = JSON.parse(text); + dailyFile = JSON.parse(text) } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Error Parsing JSON -> err = " + err.stack); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Error Parsing JSON -> err = " + err.stack) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry.") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return } } else { @@ -555,15 +555,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (err.message === 'File does not exist.' || err.code === 'The specified key does not exist.') { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Dependency Not Ready -> err = " + JSON.stringify(err)); + "[WARN] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Dependency Not Ready -> err = " + JSON.stringify(err)) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry."); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[WARN] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Asuming this is a temporary situation. Requesting a Retry.") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return } else { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Error Received -> err = " + err.stack); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> Error Received -> err = " + err.stack) callBackFunction(err) return } @@ -571,7 +571,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process const inputFilePeriod = 24 * 60 * 60 * 1000; // 24 hs let totalOutputElements = inputFilePeriod / timeFrameLabel; // this should be 2 in this case. - let beginingOutputTime = contextVariables.datetimeLastProducedFile.valueOf(); + let beginingOutputTime = contextVariables.datetimeLastProducedFile.valueOf() /* The algorithm that follows is going to agregate elements of 1 min timeFrame read from Data Dependency File, into elements of each timeFrame. @@ -750,16 +750,16 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process } } if (saveElement === true) { // then we have a valid element, otherwise it means there were no elements to fill this one in its time range. - outputElements[n].push(outputElement); + outputElements[n].push(outputElement) } } - writeFile(outputElements[n], timeFrame, controlLoop); + writeFile(outputElements[n], timeFrame, controlLoop) } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> buildOutput -> timeframesLoop -> loopBody -> nextDailyFile -> onFileReceived -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } } @@ -773,15 +773,15 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process if (n < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length) { loopBody() } else { - writeStatusReport(contextVariables.datetimeLastProducedFile, advanceTime); + writeStatusReport(contextVariables.datetimeLastProducedFile, advanceTime) } } } } catch (err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> buildOutput -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> buildOutput -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } @@ -818,10 +818,10 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process timeFrame filePath += '/' + fileName - fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated); + fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated) TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[INFO] start -> writeFile -> creating file at filePath = " + filePath); + "[INFO] start -> writeFile -> creating file at filePath = " + filePath) function onFileCreated(err) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, @@ -843,8 +843,8 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeFile -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> writeFile -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } @@ -863,7 +863,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeStatusReport -> err = " + err.stack); + "[ERROR] start -> writeStatusReport -> err = " + err.stack) callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } @@ -871,7 +871,7 @@ exports.newSuperalgosBotModulesFromOneMinToMultiPeriodMarket = function (process catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> err = " + err.stack); + "[ERROR] start -> err = " + err.stack) callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } }
  • Docs Group