Merge pull request #140 from AAMasters/develop

Indicators From UI
This commit is contained in:
Luis Fernando Molina authored and GitHub committed 2019-11-22 20:32:49 +01:00
commit 60d2e5aca1
22 files changed
+6624 -684

No files matched your search

+515
View File
@@ -0,0 +1,515 @@
exports.newCommons = function newCommons(bot, logger, UTILITIES, FILE_STORAGE) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
const MODULE_NAME = "Commons";
let thisObject = {
validateDataDependencies: validateDataDependencies,
validateOutputDatasets: validateOutputDatasets,
inflateDatafiles: inflateDatafiles,
dataBuildingProcedure: dataBuildingProcedure,
calculationsProcedure: calculationsProcedure,
generateFileContent: generateFileContent,
writeFile: writeFile
};
let utilities = UTILITIES.newCloudUtilities(logger);
let fileStorage = FILE_STORAGE.newFileStorage(logger);
return thisObject;
function validateDataDependencies(dataDependencies, callBackFunction) {
for (let i = 0; i < dataDependencies.length; i++) {
let dataDependencyNode = dataDependencies[i]
/* Basic validations to see if we have everything we need. */
if (dataDependencyNode.referenceParent.parentNode.code.singularVariableName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode.code.pluralVariableName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Plural Variable Name defined. Product Definition = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode.record === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
}
return true
}
function validateOutputDatasets(outputDatasets, callBackFunction) {
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
if (outputDatasetNode.referenceParent === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Output Dataset without Reference Parent. Output Dataset = " + JSON.stringify(outputDatasetNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.code.singularVariableName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.code.pluralVariableName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Plural Variable Name defined. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.record === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.dataBuilding === undefined) {
logger.write(MODULE_NAME, "[WARN] start -> Product Definition without a Data Building Procedure. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
}
if (outputDatasetNode.referenceParent.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Dataset witn no codeName defined. Product Dataset = " + JSON.stringify(outputDatasetNode.referenceParent));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Dataset not attached to a Product Definition. Dataset = " + JSON.stringify(outputDatasetNode.referenceParent));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition witn no codeName defined. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition not attached to a Bot. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Bot witn no codeName defined. Bot = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.parentNode.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Bot not attached to a Team. Bot = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Team witn no codeName defined. Team = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
}
return true
}
function inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timePeriod) {
/*
For each dataDependencyNode in our data dependencies, we should have a dataFile containing the records needed as an imput for this process.
What we need to do first is transform those records into JSON objects that can be used by user-defined formulas.
The first step does that but with the not calculated properties, the second step adds the calculated properties.
*/
for (let i = 0; i < dataDependencies.length; i++) {
let dataFile
let jsonData // Datafile converted into Json objects
let inputData // Includes calculated properties
let singularVariableName // name of the variable for this product
let recordDefinition
let dataDependencyNode = dataDependencies[i]
dataFile = dataFiles.get(dataDependencyNode.id)
if (dataFile === undefined) { continue } // When a datafile is not found it might be because we are processing market or daily and at the dependency array there are both types mixed up.
recordDefinition = dataDependencyNode.referenceParent.parentNode.record
singularVariableName = dataDependencyNode.referenceParent.parentNode.code.singularVariableName
/* Transform the raw data into JSON objects */
jsonData = jsonifyDataFile(dataFile, recordDefinition)
/* Add the calculated properties */
if (dataDependencyNode.referenceParent.parentNode.calculations !== undefined) {
inputData = calculationsProcedure(jsonData, recordDefinition, dataDependencyNode.referenceParent.parentNode.calculations, singularVariableName, timePeriod)
} else {
inputData = jsonData
}
products[dataDependencyNode.referenceParent.parentNode.code.pluralVariableName] = inputData
/* The main dependency is defined as the first dependency processed. */
if (mainDependency.records === undefined) {
mainDependency.records = inputData
}
}
}
function jsonifyDataFile(dataFile, recordDefinition) {
/*
This function has as an input the raw data on files and creates with it an array of JSON objects
with not calculated properties for later being consumed by Formulas
*/
let jsonifiedArray = []
let previous;
for (let i = 0; i < dataFile.length; i++) {
let record = {}
for (let j = 0; j < recordDefinition.properties.length; j++) {
let property = recordDefinition.properties[j]
if (property.code.isCalculated !== true) {
record[property.code.codeName] = dataFile[i][j]
}
}
record.previous = previous;
jsonifiedArray.push(record);
previous = record;
}
return jsonifiedArray
}
function calculationsProcedure(jsonArray, recordDefinition, calculationsProcedure, variableName, timePeriod) {
/*
This function has as an input an array of JSON objects, and it adds calculated properties to
complete the set of properties that will be available for Formulas.
*/
let system = { // These are the available system variables to be used in User Code and Formulas
timePeriod: timePeriod,
ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS
}
let variable = {} // This is the structure where the user will define its own variables that will be shared across different code blocks and formulas.
let results = []
/* This is Initialization Code */
if (calculationsProcedure.initialization !== undefined) {
if (calculationsProcedure.initialization.code !== undefined) {
try {
eval(calculationsProcedure.initialization.code.code)
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> initialization -> Error executing User Code. Error = " + err.stack)
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> initialization -> Error executing User Code. Code = " + calculationsProcedure.initialization.code.code);
throw ("Error Executing User Code.")
}
}
}
/* This is Initialization Code */
if (calculationsProcedure.loop !== undefined) {
if (calculationsProcedure.loop.code !== undefined) {
for (let index = 0; index < jsonArray.length; index++) {
let product = {}
product[variableName] = jsonArray[index]
/* This is Loop Code */
try {
eval(calculationsProcedure.loop.code.code)
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> Error executing User Code. Error = " + err.stack)
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> Error executing User Code. product = " + JSON.stringify(product))
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> Error executing User Code. Code = " + calculationsProcedure.loop.code.code);
throw ("Error Executing User Code.")
}
/* For each calculated property we apply its formula*/
for (let j = 0; j < recordDefinition.properties.length; j++) {
let property = recordDefinition.properties[j]
if (property.code.isCalculated === true) {
if (property.formula !== undefined) {
if (property.formula.code !== undefined) {
try {
let newValue = eval(property.formula.code)
let currentRecord = product[variableName]
currentRecord[property.code.codeName] = newValue
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. Error = " + err.stack)
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. product = " + JSON.stringify(product))
logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. Code = " + property.formula.code);
throw ("Error Executing User Code.")
}
}
}
}
}
/* Adding the new element to the resulting array */
results.push(product[variableName]);
}
}
}
return results
}
function dataBuildingProcedure(
products,
mainDependency,
recordDefinition,
dataBuildingProcedure,
variableName,
timePeriod,
timePeriodLabel,
resultsWithIrregularPeriods,
interExecutionMemory,
processingDailyFiles,
currentDay
) {
/*
This function has as an input the products object, with all the information
of all products calculated so far by the process. Based on that information
the function will evaluate user supplied code and formulas in order to build
a new set of information.
*/
let lastInstantOfTheDay
let yesterday = {}
let system = { // These are the available system variables to be used in User Code and Formulas
timePeriod: timePeriod,
ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS
}
let variable = {} // This is the structure where the user will define its own variables that will be shared across different code blocks and formulas.
let results = []
/* This is Initialization Code */
if (dataBuildingProcedure.initialization !== undefined) {
if (dataBuildingProcedure.initialization.code !== undefined) {
try {
eval(dataBuildingProcedure.initialization.code.code)
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> initialization -> Error executing User Code. Error = " + err.stack)
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> initialization -> Error executing User Code. Code = " + dataBuildingProcedure.initialization.code.code);
throw ("Error Executing User Code.")
}
}
}
if (processingDailyFiles) {
/* Initialization of Last Instance */
lastInstantOfTheDay = currentDay.valueOf() + ONE_DAY_IN_MILISECONDS - 1;
if (interExecutionMemory.variable === undefined) {
/* The first time the intialization variables goes to the Inter Execution Memory. */
interExecutionMemory.variable = JSON.parse(JSON.stringify(variable))
}
else {
/* We override the initialization, since the valid stuff is already at the Inter Execution Memory */
variable = JSON.parse(JSON.stringify(interExecutionMemory.variable))
}
}
/* This is Initialization Code */
if (dataBuildingProcedure.loop !== undefined) {
if (dataBuildingProcedure.loop.code !== undefined) {
let lastRecord
for (let index = 0; index < mainDependency.records.length; index++) {
let record = {
previous: mainDependency.records[index - 1],
current: mainDependency.records[index],
next: mainDependency.records[index + 1]
}
lastRecord = record
let product = {}
product[variableName] = {}
/* Here is how we know if we are processing Yesterday. */
let positionedAtYesterday = false
if (processingDailyFiles) {
positionedAtYesterday = (record.current.end < currentDay.valueOf())
}
/* This is Loop Code */
try {
eval(dataBuildingProcedure.loop.code.code)
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> Error executing User Code. Error = " + err.stack)
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> Error executing User Code. product = " + JSON.stringify(product))
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> Error executing User Code. Code = " + dataBuildingProcedure.loop.code.code);
throw ("Error Executing User Code.")
}
/* For each non-calculated property we apply its formula*/
for (let j = 0; j < recordDefinition.properties.length; j++) {
let property = recordDefinition.properties[j]
if (property.code.isCalculated !== true) {
if (property.formula !== undefined) {
if (property.formula.code !== undefined) {
try {
let newValue = eval(property.formula.code)
let currentRecord = product[variableName]
currentRecord[property.code.codeName] = newValue
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> formula -> Error executing User Code. Error = " + err.stack)
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> formula -> Error executing User Code. product = " + JSON.stringify(product))
logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> formula -> Error executing User Code. Code = " + property.formula.code);
throw ("Error Executing User Code.")
}
}
}
}
}
/* If within the code the new data structure was not yet pushed to the results array, we do it */
if (resultsWithIrregularPeriods !== true) {
/* Adding the new element to the resulting array */
results.push(product[variableName]);
}
/* While we are positioned at Yesterday, we keey updating this data structure. */
if (processingDailyFiles) {
if (positionedAtYesterday) {
yesterday.variable = JSON.parse(JSON.stringify(variable))
}
}
}
/*
Before returning we need to see if we have to record some of our counters at the interExecutionMemory.
To do that, the condition to be met is that this execution must include all candles of the current day.
*/
if (processingDailyFiles) {
if (lastRecord.current.end === lastInstantOfTheDay && yesterday.variable !== undefined) {
interExecutionMemory.variable = JSON.parse(JSON.stringify(yesterday.variable))
}
}
}
}
return results
}
function generateFileContent(records, recordDefinition, resultsWithIrregularPeriods, processingDailyFiles, currentDay, callBackFunction) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> generateFileContent -> Entering function."); }
let fileContent = "";
let recordSeparator = "";
for (let i = 0; i < records.length; i++) {
let record = records[i];
if (processingDailyFiles === true) {
if (resultsWithIrregularPeriods === true) {
/*
Here we have an special problem that occurs when an object spans several time peridos. If not taken care of
it can happen that the object gets splitted between 2 days, which we dont want since it would loose some of
its properties.
To solve this issue, we wont save objects which ends at the last candle of the day, because we will save it
at the next day, in whole, even if it starts in the previous day.
*/
let lastInstantOdDay = currentDay.valueOf() + ONE_DAY_IN_MILISECONDS - 1;
if (record.end < currentDay.valueOf() - 1) { continue; }
if (record.end === lastInstantOdDay) { continue; }
} else {
/*
The normal situation is that objects are respecting the time size of its main dependency, in which case we only
care of not adding objects of the previous day we are currently processing (while on daily files)
*/
if (record.end < currentDay.valueOf()) { continue; }
}
}
fileContent = fileContent + recordSeparator + '['
let propertySeparator = ""
for (let j = 0; j < recordDefinition.properties.length; j++) {
let property = recordDefinition.properties[j]
if (property.code.isCalculated !== true) {
fileContent = fileContent + propertySeparator
if (property.code.isString === true) {
fileContent = fileContent + '"'
}
fileContent = fileContent + record[property.code.codeName]
if (property.code.isString === true) {
fileContent = fileContent + '"'
}
if (propertySeparator === "") { propertySeparator = ","; }
}
}
fileContent = fileContent + ']'
if (recordSeparator === "") { recordSeparator = ","; }
}
fileContent = "[" + fileContent + "]";
return fileContent
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> generateFileContent -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeFile(contextSummary, fileContent, anotherFileWritten, processingDailyFiles, timePeriodLabel, currentDay, callBackFunction) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFile -> Entering function."); }
let market = global.MARKET;
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let dateForPath = ''
if (processingDailyFiles === true) {
dateForPath = "/" + currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
}
let filePathRoot = contextSummary.devTeam + "/" + contextSummary.bot + "." + contextSummary.botVersion.major + "." + contextSummary.botVersion.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + contextSummary.dataSetVersion;
let filePath = filePathRoot + "/Output/" + contextSummary.product + "/" + contextSummary.dataset + "/" + timePeriodLabel + dateForPath;
filePath += '/' + fileName
fileStorage.createTextFile(contextSummary.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
anotherFileWritten();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
+24 -10
View File
@@ -2,11 +2,12 @@
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
const MODULE_NAME = "Data Dependencies";
let bot = BOT
let thisObject = {
config: undefined,
nodeArray: undefined,
dataSets: new Map(),
initialize: initialize,
keys: []
@@ -15,15 +16,28 @@
return thisObject;
function initialize(pDataDependenciesConfig, callBackFunction) {
function initialize(callBackFunction) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
thisObject.config = pDataDependenciesConfig;
/* Basic Valdidations */
if (bot.processNode.referenceParent.processDependencies !== undefined) {
if (bot.processNode.referenceParent.processDependencies.dataDependencies !== undefined) {
thisObject.nodeArray = bot.processNode.referenceParent.processDependencies.dataDependencies
} else {
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> It is not possible to not have data dependencies at all.");
callBackFunction(global.DEFAULT_OK_RESPONSE)
return
}
} else {
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> It is not possible to not have process dependencies, which means not data dependencies.");
callBackFunction(global.DEFAULT_OK_RESPONSE)
return
}
if (thisObject.config === undefined) {
if (thisObject.nodeArray.length === 0) {
// We allow old indicators not to declare their data dependencies.
@@ -32,17 +46,17 @@
}
/*
For each dependency declared at the bot config, we will initialize a DataSet as part of this initialization process.
For each dependency declared at the nodeArray, we will initialize a DataSet as part of this initialization process.
*/
let alreadyCalledBack = false;
let addCount = 0;
for (let i = 0; i < thisObject.config.length; i++) {
for (let i = 0; i < thisObject.nodeArray.length; i++) {
let dataSetModule = DATA_SET.newDataSet(BOT, logger);
dataSetModule.initialize(thisObject.config[i], onInitilized);
dataSetModule.initialize(thisObject.nodeArray[i], onInitilized);
function onInitilized(err) {
@@ -65,14 +79,14 @@
let key;
key = thisObject.config[i].devTeam + "-" + thisObject.config[i].bot + "-" + thisObject.config[i].product + "-" + thisObject.config[i].dataSet + "-" + thisObject.config[i].dataSetVersion;
key = thisObject.nodeArray[i].devTeam + "-" + thisObject.nodeArray[i].bot + "-" + thisObject.nodeArray[i].product + "-" + thisObject.nodeArray[i].dataSet + "-" + thisObject.nodeArray[i].dataSetVersion;
thisObject.keys.push(key);
thisObject.dataSets.set(key, dataSetModule);
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> addDataSet -> DataSet added to Map. -> key = " + key); }
if (addCount === thisObject.config.length) {
if (addCount === thisObject.nodeArray.length) {
if (alreadyCalledBack === false) {
alreadyCalledBack = true
callBackFunction(global.DEFAULT_OK_RESPONSE);
+71 -11
View File
@@ -1,6 +1,6 @@
exports.newDataSet = function newDataSet(BOT, logger) {
const MODULE_NAME = "Data Set";
const MODULE_NAME = "Dataset";
let bot = BOT;
@@ -10,7 +10,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
createTextFile: createTextFile
};
let dependencyConfig;
let dataDependencyNode;
/* Storage account to be used here. */
@@ -19,16 +19,76 @@ exports.newDataSet = function newDataSet(BOT, logger) {
return thisObject;
function initialize(pDependencyConfig, callBackFunction) {
function initialize(pDataDependencyNode, callBackFunction) {
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
logger.fileName = MODULE_NAME + "." + pDependencyConfig.bot + "." + pDependencyConfig.product + "." + pDependencyConfig.dataSet;
dataDependencyNode = pDataDependencyNode;
logger.fileName = MODULE_NAME + "." + dataDependencyNode.type + "." + dataDependencyNode.name + "." + dataDependencyNode.id;
dependencyConfig = pDependencyConfig;
/* Some very basic validations that we have all the information needed. */
if (dataDependencyNode.referenceParent === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Data Dependency without Reference Parent. Data Dependency = " + JSON.stringify(dataDependencyNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Dataset witn no codeName defined. Product Dataset = " + JSON.stringify(dataDependencyNode.referenceParent));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Dataset not attached to a Product Definition. Dataset = " + JSON.stringify(dataDependencyNode.referenceParent));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Product Definition witn no codeName defined. Product Definition = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Product Definition not attached to a Bot. Product Definition = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Bot witn no codeName defined. Bot = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode.parentNode.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Bot not attached to a Team. Bot = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (dataDependencyNode.referenceParent.parentNode.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Team witn no codeName defined. Team = " + JSON.stringify(dataDependencyNode.referenceParent.parentNode.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
/* Simplifying the access to basic info */
dataDependencyNode.dataSet = dataDependencyNode.referenceParent.code.codeName
dataDependencyNode.product = dataDependencyNode.referenceParent.parentNode.code.codeName
dataDependencyNode.bot = dataDependencyNode.referenceParent.parentNode.parentNode.code.codeName
dataDependencyNode.devTeam = dataDependencyNode.referenceParent.parentNode.parentNode.parentNode.code.codeName
/* This stuff is still hardcoded and unresolved. */
dataDependencyNode.botVersion = {
"major": 1,
"minor": 0
}
dataDependencyNode.dataSetVersion = "dataSet.V1"
callBackFunction(global.DEFAULT_OK_RESPONSE);
@@ -44,11 +104,11 @@ exports.newDataSet = function newDataSet(BOT, logger) {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getTextFile -> Entering function."); }
let filePathRoot = dependencyConfig.devTeam + "/" + dependencyConfig.bot + "." + dependencyConfig.botVersion.major + "." + dependencyConfig.botVersion.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + dependencyConfig.dataSetVersion;
let filePathRoot = dataDependencyNode.devTeam + "/" + dataDependencyNode.bot + "." + dataDependencyNode.botVersion.major + "." + dataDependencyNode.botVersion.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + dataDependencyNode.dataSetVersion;
let filePath = filePathRoot + "/Output/" + pFolderPath;
filePath += '/' + pFileName
fileStorage.getTextFile(dependencyConfig.devTeam, filePath, onFileReceived);
fileStorage.getTextFile(dataDependencyNode.devTeam, filePath, onFileReceived);
function onFileReceived(err, text) {
@@ -72,7 +132,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createTextFile -> pFolderPath = " + pFolderPath); }
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createTextFile -> pFileName = " + pFileName); }
let ownerId = dependencyConfig.devTeam + "-" + dependencyConfig.bot + "-" + dependencyConfig.botVersion.major + "-" + dependencyConfig.botVersion.minor + "-" + dependencyConfig.dataSetVersion;
let ownerId = dataDependencyNode.devTeam + "-" + dataDependencyNode.bot + "-" + dataDependencyNode.botVersion.major + "-" + dataDependencyNode.botVersion.minor + "-" + dataDependencyNode.dataSetVersion;
let botId = bot.devTeam + "-" + bot.codeName + "-" + bot.version.major + "-" + bot.version.minor + "-" + bot.dataSetVersion;
if (ownerId !== botId) {
@@ -86,10 +146,10 @@ exports.newDataSet = function newDataSet(BOT, logger) {
return;
}
let filePathRoot = dependencyConfig.devTeam + "/" + dependencyConfig.bot + "." + dependencyConfig.botVersion.major + "." + dependencyConfig.botVersion.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + dependencyConfig.dataSetVersion;
let filePathRoot = dataDependencyNode.devTeam + "/" + dataDependencyNode.bot + "." + dataDependencyNode.botVersion.major + "." + dataDependencyNode.botVersion.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + dataDependencyNode.dataSetVersion;
let filePath = filePathRoot + "/Output/" + pFolderPath + '/' + pFileName;
fileStorage.createTextFile(dependencyConfig.devTeam, filePath, pFileContent, onFileCreated);
fileStorage.createTextFile(dataDependencyNode.devTeam, filePath, pFileContent, onFileCreated);
function onFileCreated(err) {
+12 -13
View File
@@ -21,9 +21,7 @@ exports.newDebugLog = function newDebugLog() {
};
let accumulatedLog = "[";
let disableLogging;
let internalLoopCounter = -1;
return thisObject;
@@ -80,35 +78,32 @@ exports.newDebugLog = function newDebugLog() {
}
let fileName;
if (internalLoopCounter >= 0) {
fileName = "Loop." + pad(thisObject.bot.loopCounter, 8) + "." + pad(internalLoopCounter, 4) + ".json";
} else {
fileName = "Loop." + pad(thisObject.bot.loopCounter, 8) + ".json";
}
writeLog();
/* This is the implementation of the mechanism to auto-mantain logs. */
thisObject.bot.LOGS_TO_DELETE_QUEUE.push(filePath + '/' + fileName)
if (thisObject.bot.LOGS_TO_DELETE_QUEUE.length > thisObject.bot.DELETE_QUEUE_SIZE) {
let fileToDelete = thisObject.bot.LOGS_TO_DELETE_QUEUE[0]
thisObject.bot.LOGS_TO_DELETE_QUEUE.splice(0,1)
fileStorage.deleteTextFile(thisObject.bot.devTeam, fileToDelete);
}
function writeLog() {
fileStorage.createTextFile(thisObject.bot.devTeam, filePath + '/' + fileName, contentToPersist + '\r\n' + "]", onFileCreated);
function onFileCreated(err) {
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
console.log("[ERROR] DebugLog -> persist -> onInizialized -> onFileCreated -> err = "+ err.message);
setTimeout(writeLog, 10000); // Lets retry until we make it.
return;
}
contentToPersist = "";
//thisObject = {};
}
}
} catch (err) {
@@ -126,6 +121,10 @@ exports.newDebugLog = function newDebugLog() {
if (thisObject.bot === undefined) { return; }
if (pModule === "") { // For debugging purposes
console.log(pMessage)
}
let newDate = new Date();
newDate = newDate.toISOString();
+56 -1
View File
@@ -19,7 +19,8 @@ exports.newFileStorage = function newFileStorage(logger) {
let thisObject = {
getTextFile: getTextFile,
createTextFile: createTextFile
createTextFile: createTextFile,
deleteTextFile: deleteTextFile
}
return thisObject
@@ -207,6 +208,60 @@ exports.newFileStorage = function newFileStorage(logger) {
}
}
function deleteTextFile(container, filePath, callBackFunction) {
logger.write(MODULE_NAME, '[INFO] FileStorage -> deleteTextFile -> Entering Function.')
container = container.toLowerCase()
/* Choose path for either logs or data */
let fileLocation
if (filePath.indexOf("/Logs/") > 0) {
fileLocation = process.env.LOG_PATH + '/' + container + '/' + filePath
} else {
fileLocation = process.env.STORAGE_PATH + '/' + container + '/' + filePath
}
try {
logger.write(MODULE_NAME, '[INFO] FileStorage -> deleteTextFile -> fileLocation: ' + fileLocation)
const fs = require('fs')
fs.unlink(fileLocation, onUnlinked)
function onUnlinked(err) {
if (err) {
if (callBackFunction !== undefined) {
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
}
} else {
if (callBackFunction !== undefined) {
callBackFunction(global.DEFAULT_OK_RESPONSE)
}
}
}
} catch (err) {
logger.write(MODULE_NAME, '[WARN] FileStorage -> deleteTextFile -> Error writing file -> file = ' + fileLocation)
logger.write(MODULE_NAME, '[WARN] FileStorage -> deleteTextFile -> Error writing file -> err = ' + err.stack)
if (callBackFunction !== undefined) {
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
}
}
function retry() {
if (currentRetryWriteTextFile < MAX_RETRY) {
currentRetryWriteTextFile++
logger.write(MODULE_NAME, '[WARN] FileStorage -> createTextFile -> retry -> Will try to write the file again -> Retry #: ' + currentRetryWriteTextFile)
createTextFile(container, filePath, fileContent, callBackFunction)
} else {
currentRetryWriteTextFile = 0
logger.write(MODULE_NAME, '[ERROR] FileStorage -> createTextFile -> retry -> Max retries reached writting a file. Giving up.')
logger.write(MODULE_NAME, '[ERROR] FileStorage -> createTextFile -> retry -> file = ' + fileLocation)
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
}
}
}
/* Function to create folders of missing folders at any path. */
function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
+164
View File
@@ -0,0 +1,164 @@
exports.newIndicatorBot = function newIndicatorBot(bot, logger, UTILITIES, FILE_STORAGE) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
const MODULE_NAME = "Indicator Bot";
let thisObject = {
initialize: initialize,
finalize: finalize,
start: start
};
let utilities = UTILITIES.newCloudUtilities(logger);
let fileStorage = FILE_STORAGE.newFileStorage(logger);
const COMMONS = require('./Commons.js');
let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE);
return thisObject;
function finalize() {
thisObject = undefined
utilities = undefined
fileStorage = undefined
commons = undefined
}
function initialize(callBackFunction) {
try {
logger.fileName = MODULE_NAME;
logger.initialize();
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function start(dataFiles, timePeriod, timePeriodLabel, currentDay, interExecutionMemory, callBackFunction) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
let products = {}
let mainDependency = {}
let processingDailyFiles
if (currentDay !== undefined) {
processingDailyFiles = true
} else {
processingDailyFiles = false
}
/* The first phase here is about checking that we have everything we need at the definition level. */
let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies
if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) { return }
let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets
if (commons.validateOutputDatasets(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. */
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timePeriod)
/* During the third phase, we need to generate the data of the different products this process produces an output */
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let jsonData // Just build data as Json objects
let outputData // Data built as a result of applying user defined code and formulas at the Data Building Procedure
let singularVariableName // Name of the variable for this product
let recordDefinition // Record as defined by the user at the UI
let fileContent // Here we store the contents of the new data built just before writing it to a file.
let resultsWithIrregularPeriods // A product will have irregular periods when the User Code inserts new result records at will, in contrast with normal procedure where the platform insert one record per loop execution.
/*
For each outputDatasetNode in our process output, we will build the information based on our input products.
*/
recordDefinition = outputDatasetNode.referenceParent.parentNode.record
singularVariableName = outputDatasetNode.referenceParent.parentNode.code.singularVariableName
/* Check Irregular Periods */
if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.code.code.indexOf('results.push') >= 0) {
resultsWithIrregularPeriods = true
}
/* Build the data */
jsonData = commons.dataBuildingProcedure(
products,
mainDependency,
recordDefinition,
outputDatasetNode.referenceParent.parentNode.dataBuilding,
singularVariableName,
timePeriod,
timePeriodLabel,
resultsWithIrregularPeriods,
interExecutionMemory,
processingDailyFiles,
currentDay
)
/* Add the calculated properties */
if (outputDatasetNode.referenceParent.parentNode.calculations !== undefined) {
outputData = commons.calculationsProcedure(jsonData, recordDefinition, outputDatasetNode.referenceParent.parentNode.calculations, singularVariableName, timePeriod)
} else {
outputData = jsonData
}
products[outputDatasetNode.referenceParent.parentNode.code.pluralVariableName] = outputData
}
/*At the fourth and last phase, we will save the new information generated into files corresponding to each output outputDatasetNode.*/
let totalFilesWritten = 0
for (let i = 0; i < outputDatasets.length; i++) {
let outputDatasetNode = outputDatasets[i]
let outputData = products[outputDatasetNode.referenceParent.parentNode.code.pluralVariableName]
let resultsWithIrregularPeriods // A product will have irregular periods when the User Code inserts new result records at will, in contrast with normal procedure where the platform insert one record per loop execution.
let contextSummary = {}
/* Check Irregular Periods */
if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.code.code.indexOf('results.push') >= 0) {
resultsWithIrregularPeriods = true
}
/* Simplifying the access to basic info */
contextSummary.dataset = outputDatasetNode.referenceParent.code.codeName
contextSummary.product = outputDatasetNode.referenceParent.parentNode.code.codeName
contextSummary.bot = outputDatasetNode.referenceParent.parentNode.parentNode.code.codeName
contextSummary.devTeam = outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.code.codeName
/* This stuff is still hardcoded and unresolved. */
contextSummary.botVersion = {
"major": 1,
"minor": 0
}
contextSummary.dataSetVersion = "dataSet.V1"
let fileContent = commons.generateFileContent(outputData, outputDatasetNode.referenceParent.parentNode.record, resultsWithIrregularPeriods, processingDailyFiles, currentDay, callBackFunction)
commons.writeFile(contextSummary, fileContent, anotherFileWritten, processingDailyFiles, timePeriodLabel, currentDay, callBackFunction)
}
function anotherFileWritten() {
totalFilesWritten++
if (totalFilesWritten === outputDatasets.length) {
callBackFunction(global.DEFAULT_OK_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
};
+320 -14
View File
@@ -29,15 +29,21 @@
return thisObject;
function initialize(pProcessConfig, callBackFunction) {
/* This function is exactly the same in the 3 modules representing the 2 different bot types loops. */
try {
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
processConfig = pProcessConfig;
let filePath = bot.devTeam + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name
if (bot.definedByUI === true) {
/* The code of the bot is defined at the UI. No need to load a file with the code. */
callBackFunction(global.DEFAULT_OK_RESPONSE);
return
}
/* This bot is not ready for taking its code from the UI, then we need to load it from its repo. */
let filePath = bot.devTeam + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.codeName
filePath += "/User.Bot.js"
fileStorage.getTextFile(bot.devTeam, filePath, onBotDownloaded);
@@ -47,6 +53,7 @@
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> err = " + err.message);
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> filePath = " + filePath);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
@@ -129,6 +136,8 @@
const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies');
const DATA_DEPENDENCIES = require(ROOT_DIR + 'DataDependencies');
const DATA_SET = require(ROOT_DIR + 'DataSet');
const PROCESS_EXECUTION_EVENTS = require(ROOT_DIR + 'ProcessExecutionEvents');
const PROCESS_OUTPUT = require(ROOT_DIR + 'ProcessOutput');
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
@@ -141,6 +150,8 @@
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
let processOutput
let processExecutionEvents
let userBot;
let processFramework;
let statusDependencies;
@@ -148,7 +159,155 @@
let nextWaitTime;
initializeStatusDependencies();
initializeProcessExecutionEvents();
function initializeProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> Entering function."); }
processExecutionEvents = PROCESS_EXECUTION_EVENTS.newProcessExecutionEvents(bot, logger)
processExecutionEvents.initialize(pMonth, pYear, onInizialized);
function onInizialized(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Execution finished well.");
startProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function startProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> Entering function."); }
processExecutionEvents.start(onStarted);
function onStarted(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Execution finished well.");
initializeStatusDependencies();
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessExecutionEvents -> onStarted -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function initializeStatusDependencies() {
@@ -158,7 +317,7 @@
statusDependencies = STATUS_DEPENDENCIES.newStatusDependencies(bot, logger, STATUS_REPORT, UTILITIES);
statusDependencies.initialize(processConfig.statusDependencies, pMonth, pYear, onInizialized);
statusDependencies.initialize(pMonth, pYear, onInizialized);
function onInizialized(err) {
@@ -233,7 +392,7 @@
dataDependencies = DATA_DEPENDENCIES.newDataDependencies(bot, logger, DATA_SET);
dataDependencies.initialize(processConfig.dataDependencies, onInizialized);
dataDependencies.initialize(onInizialized);
function onInizialized(err) {
@@ -253,12 +412,12 @@
switch (processConfig.framework.name) {
case 'Multi-Period-Market': {
processFramework = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE);
processFramework = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, UTILITIES, FILE_STORAGE);
intitializeProcessFramework();
break;
}
case 'Multi-Period-Daily': {
processFramework = MULTI_PERIOD_DAILY.newMultiPeriodDaily(bot, logger, COMMONS_MODULE, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE);
processFramework = MULTI_PERIOD_DAILY.newMultiPeriodDaily(bot, logger, UTILITIES, FILE_STORAGE);
intitializeProcessFramework();
break;
}
@@ -448,8 +607,7 @@
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> onFinished -> Execution finished well.");
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
raiseEventsProcessOutput()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
@@ -568,7 +726,7 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> Entering function."); }
processFramework.initialize(processConfig, statusDependencies, dataDependencies, undefined, onInizialized);
processFramework.initialize(processConfig, statusDependencies, dataDependencies, onInizialized);
function onInizialized(err) {
@@ -681,8 +839,7 @@
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Execution finished well.");
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
raiseEventsProcessOutput()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
@@ -795,6 +952,155 @@
}
}
function raiseEventsProcessOutput() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> Entering function."); }
processOutput = PROCESS_OUTPUT.newProcessOutput(bot, logger)
processOutput.raiseEvents(statusDependencies, onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> onFinished -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> onFinished -> Execution finished well.");
finishProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> raiseEventsProcessOutput -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function finishProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> Entering function."); }
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Execution finished well.");
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> finishProcessExecutionEvents -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function loopControl(nextWaitTime) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Entering function."); }
+52 -60
View File
@@ -1,4 +1,4 @@
exports.newMultiPeriod = function newMultiPeriod(bot, logger, COMMONS, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE) {
exports.newMultiPeriod = function newMultiPeriod(bot, logger, UTILITIES, USER_BOT_MODULE, USER_BOT_COMMONS) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
@@ -16,11 +16,11 @@
let statusDependencies;
let dataDependencies;
let storages = [];
let dataFiles = [];
let datasets = [];
let dataFiles = new Map();
let multiPeriodDataFiles = new Map();
let usertBot;
let botInstance;
const FILE_STORAGE = require('./FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage(logger);
@@ -42,11 +42,11 @@
dataDependencies = pDataDependencies;
processConfig = pProcessConfig;
for (let i = 0; i < dataDependencies.config.length; i++) {
for (let i = 0; i < dataDependencies.nodeArray.length; i++) {
let key;
let storage;
let dependency = dataDependencies.config[i];
let dataset;
let dependency = dataDependencies.nodeArray[i];
key = dependency.devTeam + "-" +
dependency.bot + "-" +
@@ -54,14 +54,16 @@
dependency.dataSet + "-" +
dependency.dataSetVersion
storage = dataDependencies.dataSets.get(key);
dataset = dataDependencies.dataSets.get(key);
storages.push(storage);
datasets.push(dataset);
}
usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, fileStorage);
usertBot.initialize(callBackFunction, pAssistant);
let USER_BOT_MODULE = require("./TradingBot")
botInstance = USER_BOT_MODULE.newTradingBot(bot, logger, UTILITIES, FILE_STORAGE);
botInstance.initialize(pAssistant, callBackFunction);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
@@ -70,13 +72,13 @@
}
function finalize() {
storages = undefined
datasets = undefined
dataFiles = undefined
multiPeriodDataFiles = undefined
statusDependencies = undefined
dataDependencies = undefined
usertBot.finalize()
usertBot = undefined
botInstance.finalize()
botInstance = undefined
fileStorage = undefined
processConfig = undefined
thisObject = undefined
@@ -125,12 +127,7 @@
Here we get the status report from the bot who knows which is the end of the market.
*/
let botWhoKnowsTheEndOfTheMarket = statusDependencies.config[processConfig.framework.endDate.takeItFromStatusDependency];
reportKey = botWhoKnowsTheEndOfTheMarket.devTeam + "-" + botWhoKnowsTheEndOfTheMarket.bot + "-" + botWhoKnowsTheEndOfTheMarket.process + "-" + "dataSet.V1";
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
statusReport = statusDependencies.statusReports.get(reportKey);
statusReport = statusDependencies.reportsByMainUtility.get("Market Ending Point")
if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month.
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ");
@@ -144,7 +141,7 @@
return;
}
thisReport = statusDependencies.statusReports.get(reportKey).file;
thisReport = statusReport.file;
if (thisReport.lastFile === undefined) {
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey);
@@ -174,10 +171,7 @@
/* Finally we get our own Status Report. */
reportKey = bot.devTeam + "-" + bot.codeName + "-" + "Multi-Period" + "-" + "dataSet.V1";
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
statusReport = statusDependencies.statusReports.get(reportKey);
statusReport = statusDependencies.reportsByMainUtility.get("Self Reference")
if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month.
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ");
@@ -191,7 +185,7 @@
return;
}
thisReport = statusDependencies.statusReports.get(reportKey).file;
thisReport = statusReport.file;
if (thisReport.lastFile !== undefined) {
@@ -290,12 +284,12 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriodsMarketFiles -> periodsLoopBody -> Entering function."); }
const timePeriod = global.marketFilesPeriods[n][0];
const outputPeriodLabel = global.marketFilesPeriods[n][1];
const timePeriodLabel = global.marketFilesPeriods[n][1];
let dependencyIndex = 0;
dataFiles = [];
dataFiles = new Map();
if (bot.VALUES_TO_USE.timePeriod === outputPeriodLabel) {
if (bot.VALUES_TO_USE.timePeriod === timePeriodLabel) {
currentTimePeriod = global.marketFilesPeriods[n][0];
currentOutputPeriodName = global.marketFilesPeriods[n][1];
}
@@ -307,8 +301,8 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriodsMarketFiles -> periodsLoopBody -> dependencyLoopBody -> Entering function."); }
let dependency = dataDependencies.config[dependencyIndex];
let storage = storages[dependencyIndex];
let dependency = dataDependencies.nodeArray[dependencyIndex];
let dataset = datasets[dependencyIndex];
getFile();
@@ -326,9 +320,9 @@
return
}
let filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel;
let filePath = dependency.product + '/' + dependency.dataSet + "/" + timePeriodLabel;
storage.getTextFile(filePath, fileName, onFileReceived);
dataset.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
@@ -345,7 +339,7 @@
}
let dataFile = JSON.parse(text);
dataFiles.push(dataFile);
dataFiles.set(dependency.id, dataFile);
dependencyControlLoop();
@@ -377,7 +371,7 @@
dependencyIndex++;
if (dependencyIndex < dataDependencies.config.length) {
if (dependencyIndex < dataDependencies.nodeArray.length) {
dependencyLoopBody();
@@ -581,28 +575,28 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriodsDailyFiles -> periodsLoopBody -> Entering function."); }
const timePeriod = global.dailyFilePeriods[n][0];
const outputPeriodLabel = global.dailyFilePeriods[n][1];
const timePeriodLabel = global.dailyFilePeriods[n][1];
if (processConfig.framework.validPeriods !== undefined) {
let validPeriod = false;
for (let i = 0; i < processConfig.framework.validPeriods.length; i++) {
let period = processConfig.framework.validPeriods[i];
if (period === outputPeriodLabel) { validPeriod = true }
if (period === timePeriodLabel) { validPeriod = true }
}
if (validPeriod === false) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriodsDailyFiles -> periodsLoopBody -> Discarding period for not being listed as a valid period. -> outputPeriodLabel = " + outputPeriodLabel); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriodsDailyFiles -> periodsLoopBody -> Discarding period for not being listed as a valid period. -> timePeriodLabel = " + timePeriodLabel); }
periodsControlLoop();
return;
}
}
if (bot.VALUES_TO_USE.timePeriod === outputPeriodLabel) {
if (bot.VALUES_TO_USE.timePeriod === timePeriodLabel) {
currentTimePeriod = global.dailyFilePeriods[n][0];
currentOutputPeriodName = global.dailyFilePeriods[n][1];
}
let dependencyIndex = 0;
dataFiles = [];
dataFiles = new Map();
dependencyLoopBody();
function dependencyLoopBody() {
@@ -611,8 +605,8 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriodsDailyFiles -> periodsLoopBody -> dependencyLoopBody -> Entering function."); }
let dependency = dataDependencies.config[dependencyIndex];
let storage = storages[dependencyIndex];
let dependency = dataDependencies.nodeArray[dependencyIndex];
let dataset = datasets[dependencyIndex];
let previousFile;
let currentFile;
@@ -640,13 +634,13 @@
let filePath
if (dependency.dataSet === "Multi-Period-Daily") {
filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel + "/" + dateForPath;
filePath = dependency.product + '/' + dependency.dataSet + "/" + timePeriodLabel + "/" + dateForPath;
} else {
filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath;
}
let fileName = market.assetA + '_' + market.assetB + ".json";
storage.getTextFile(filePath, fileName, onFileReceived);
dataset.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
@@ -716,13 +710,13 @@
let dateForPath = bot.multiPeriodProcessDatetime.getUTCFullYear() + '/' + utilities.pad(bot.multiPeriodProcessDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.multiPeriodProcessDatetime.getUTCDate(), 2);
let filePath
if (dependency.dataSet === "Multi-Period-Daily") {
filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel + "/" + dateForPath;
filePath = dependency.product + '/' + dependency.dataSet + "/" + timePeriodLabel + "/" + dateForPath;
} else {
filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath;
}
let fileName = market.assetA + '_' + market.assetB + ".json";
storage.getTextFile(filePath, fileName, onFileReceived);
dataset.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
@@ -754,7 +748,7 @@
let dataFile = previousFile.concat(currentFile);
dataFiles.push(dataFile);
dataFiles.set(dependency.id, dataFile);
dependencyControlLoop();
@@ -785,7 +779,7 @@
dependencyIndex++;
if (dependencyIndex < dataDependencies.config.length) {
if (dependencyIndex < dataDependencies.nodeArray.length) {
dependencyLoopBody();
@@ -847,7 +841,7 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriodsDailyFiles -> callTheBot -> Entering function."); }
usertBot.start(
botInstance.start(
multiPeriodDataFiles,
currentTimePeriod,
currentOutputPeriodName,
@@ -959,21 +953,19 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRanges -> Entering function."); }
let productIndex = 0;
productLoopBody();
let outputDatasetIndex = -1;
controlLoop();
function productLoopBody() {
let product = bot.products[productIndex];
writeDataRange(contextVariables.dateBeginOfMarket, bot.multiPeriodProcessDatetime, product, currentOutputPeriodName, controlLoop);
let productCodeName = bot.processNode.referenceParent.processOutput.outputDatasets[outputDatasetIndex].referenceParent.parentNode.code.codeName;
writeDataRange(contextVariables.dateBeginOfMarket, bot.multiPeriodProcessDatetime, productCodeName, currentOutputPeriodName, controlLoop);
}
function controlLoop() {
productIndex++;
outputDatasetIndex++;
if (productIndex < bot.products.length) {
if (outputDatasetIndex < bot.processNode.referenceParent.processOutput.outputDatasets.length) {
productLoopBody();
} else {
callBack(global.DEFAULT_OK_RESPONSE);
@@ -987,7 +979,7 @@
}
function writeDataRange(pBegin, pEnd, product, currentOutputPeriodName, callBack) {
function writeDataRange(pBegin, pEnd, productCodeName, currentOutputPeriodName, callBack) {
try {
@@ -1001,7 +993,7 @@
let fileContent = JSON.stringify(dataRange);
let fileName = '/Data.Range.' + market.assetA + '_' + market.assetB + '.json';
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + product.codeName + "/" + 'Multi-Period-Daily' + fileName;
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + productCodeName + "/" + 'Multi-Period-Daily' + fileName;
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
@@ -1019,7 +1011,7 @@
logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Content written = " + fileContent);
}
let key = bot.devTeam + "-" + bot.codeName + "-" + product.codeName + "-" + currentOutputPeriodName
let key = bot.devTeam + "-" + bot.codeName + "-" + productCodeName + "-" + currentOutputPeriodName
let event = {
dateRange: dataRange
}
+46 -62
View File
@@ -1,4 +1,4 @@
exports.newMultiPeriodDaily = function newMultiPeriodDaily(bot, logger, COMMONS, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE) {
exports.newMultiPeriodDaily = function newMultiPeriodDaily(bot, logger, UTILITIES, FILE_STORAGE) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
@@ -16,12 +16,11 @@
let statusDependencies;
let dataDependencies;
let storages = [];
let dataFiles = [];
let datasets = [];
let dataFiles = new Map;
let usertBot;
let botInstance;
const FILE_STORAGE = require('./FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage(logger);
let bootstrappingTheProcess = false
@@ -30,7 +29,7 @@
return thisObject;
function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, pAssistant, callBackFunction) {
function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, callBackFunction) {
try {
@@ -43,11 +42,11 @@
dataDependencies = pDataDependencies;
processConfig = pProcessConfig;
for (let i = 0; i < dataDependencies.config.length; i++) {
for (let i = 0; i < dataDependencies.nodeArray.length; i++) {
let key;
let storage;
let dependency = dataDependencies.config[i];
let dataset;
let dependency = dataDependencies.nodeArray[i];
key = dependency.devTeam + "-" +
dependency.bot + "-" +
@@ -55,14 +54,16 @@
dependency.dataSet + "-" +
dependency.dataSetVersion
storage = dataDependencies.dataSets.get(key);
dataset = dataDependencies.dataSets.get(key);
storages.push(storage);
datasets.push(dataset);
}
usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, fileStorage);
usertBot.initialize(dataDependencies, callBackFunction, pAssistant);
let USER_BOT_MODULE = require("./IndicatorBot")
botInstance = USER_BOT_MODULE.newIndicatorBot(bot, logger, UTILITIES, FILE_STORAGE);
botInstance.initialize(callBackFunction);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
@@ -71,11 +72,11 @@
}
function finalize() {
storages = undefined
datasets = undefined
dataFiles = undefined
statusDependencies = undefined
dataDependencies = undefined
usertBot = undefined
botInstance = undefined
fileStorage = undefined
processConfig = undefined
thisObject = undefined
@@ -126,12 +127,7 @@
We look first for the bot who knows the begining of the marke in order to get when the market starts.
*/
let botWhoKnowsTheBeginingOfTheMarket = statusDependencies.config[processConfig.framework.startDate.takeItFromStatusDependency];
reportKey = botWhoKnowsTheBeginingOfTheMarket.devTeam + "-" + botWhoKnowsTheBeginingOfTheMarket.bot + "-" + botWhoKnowsTheBeginingOfTheMarket.process + "-" + "dataSet.V1";
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
statusReport = statusDependencies.statusReports.get(reportKey);
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.
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ");
@@ -145,7 +141,7 @@
return;
}
thisReport = statusDependencies.statusReports.get(reportKey).file;
thisReport = statusReport.file;
if (thisReport.lastFile === undefined) {
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey);
@@ -168,7 +164,7 @@
/* The ending date is fixed, we will end there. */
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> We have got a user defined endDate. -> endDate = " + processConfig.framework.endDate.fixedDate); }
contextVariables.dateEndOfMarket = new Date(processConfig.framework.endDate.fixedDate);
contextVariables.dateEndOfMarket = new Date(processConfig.framework.endDate.fixedDate);
} else {
@@ -176,12 +172,7 @@
Here we get the status report from the bot who knows which is the end of the market.
*/
let botWhoKnowsTheEndOfTheMarket = statusDependencies.config[processConfig.framework.endDate.takeItFromStatusDependency];
reportKey = botWhoKnowsTheEndOfTheMarket.devTeam + "-" + botWhoKnowsTheEndOfTheMarket.bot + "-" + botWhoKnowsTheEndOfTheMarket.process + "-" + "dataSet.V1";
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
statusReport = statusDependencies.statusReports.get(reportKey);
statusReport = statusDependencies.reportsByMainUtility.get("Market Ending Point")
if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month.
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ");
@@ -195,7 +186,7 @@
return;
}
thisReport = statusDependencies.statusReports.get(reportKey).file;
thisReport = statusReport.file;
if (thisReport.lastFile === undefined) {
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey);
@@ -214,10 +205,7 @@
/* Finally we get our own Status Report. */
reportKey = bot.devTeam + "-" + bot.codeName + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
statusReport = statusDependencies.statusReports.get(reportKey);
statusReport = statusDependencies.reportsByMainUtility.get("Self Reference")
if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month.
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ");
@@ -231,7 +219,7 @@
return;
}
thisReport = statusDependencies.statusReports.get(reportKey).file;
thisReport = statusReport.file;
if (thisReport.lastFile !== undefined) {
@@ -382,23 +370,23 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Entering function."); }
const timePeriod = global.dailyFilePeriods[n][0];
const outputPeriodLabel = global.dailyFilePeriods[n][1];
const timePeriodLabel = global.dailyFilePeriods[n][1];
if (processConfig.framework.validPeriods !== undefined) {
let validPeriod = false;
for (let i = 0; i < processConfig.framework.validPeriods.length; i++) {
let period = processConfig.framework.validPeriods[i];
if (period === outputPeriodLabel) { validPeriod = true }
if (period === timePeriodLabel) { validPeriod = true }
}
if (validPeriod === false) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Discarding period for not being listed as a valid period. -> outputPeriodLabel = " + outputPeriodLabel); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Discarding period for not being listed as a valid period. -> timePeriodLabel = " + timePeriodLabel); }
periodsControlLoop();
return;
}
}
let dependencyIndex = 0;
dataFiles = [];
dataFiles = new Map();
dependencyLoopBody();
@@ -408,8 +396,8 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> Entering function."); }
let dependency = dataDependencies.config[dependencyIndex];
let storage = storages[dependencyIndex];
let dependency = dataDependencies.nodeArray[dependencyIndex];
let dataset = datasets[dependencyIndex];
let previousFile;
let currentFile;
@@ -430,13 +418,13 @@
let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2);
let filePath
if (dependency.dataSet === "Multi-Period-Daily") {
filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel + "/" + dateForPath;
filePath = dependency.product + '/' + dependency.dataSet + "/" + timePeriodLabel + "/" + dateForPath;
} else {
filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath;
}
let fileName = market.assetA + '_' + market.assetB + ".json";
storage.getTextFile(filePath, fileName, onFileReceived);
dataset.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
@@ -500,13 +488,13 @@
let dateForPath = bot.multiPeriodDailyProcessDatetime.getUTCFullYear() + '/' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCDate(), 2);
let filePath
if (dependency.dataSet === "Multi-Period-Daily") {
filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel + "/" + dateForPath;
filePath = dependency.product + '/' + dependency.dataSet + "/" + timePeriodLabel + "/" + dateForPath;
} else {
filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath;
}
let fileName = market.assetA + '_' + market.assetB + ".json";
storage.getTextFile(filePath, fileName, onFileReceived);
dataset.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
@@ -545,7 +533,7 @@
let dataFile = previousFile.concat(currentFile);
dataFiles.push(dataFile);
dataFiles.set(dependency.id, dataFile);
dependencyControlLoop();
}
@@ -575,7 +563,7 @@
dependencyIndex++;
if (dependencyIndex < dataDependencies.config.length) {
if (dependencyIndex < dataDependencies.nodeArray.length) {
dependencyLoopBody();
@@ -598,15 +586,13 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> Entering function."); }
const timePeriod = global.dailyFilePeriods[n][0];
const outputPeriodLabel = global.dailyFilePeriods[n][1];
const timePeriodLabel = global.dailyFilePeriods[n][1];
usertBot.start(
botInstance.start(
dataFiles,
timePeriod,
outputPeriodLabel,
timePeriodLabel,
bot.multiPeriodDailyProcessDatetime,
contextVariables.dateBeginOfMarket,
contextVariables.dateEndOfMarket,
interExecutionMemoryArray[n],
onBotFinished);
@@ -701,21 +687,19 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRanges -> Entering function."); }
let productIndex = 0;
productLoopBody();
let outputDatasetIndex = -1;
controlLoop();
function productLoopBody() {
let folderName = bot.products[productIndex].codeName;
writeDataRange(contextVariables.dateBeginOfMarket, bot.multiPeriodDailyProcessDatetime, folderName, controlLoop);
let productCodeName = bot.processNode.referenceParent.processOutput.outputDatasets[outputDatasetIndex].referenceParent.parentNode.code.codeName;
writeDataRange(contextVariables.dateBeginOfMarket, bot.multiPeriodDailyProcessDatetime, productCodeName, controlLoop);
}
function controlLoop() {
productIndex++;
outputDatasetIndex++;
if (productIndex < bot.products.length) {
if (outputDatasetIndex < bot.processNode.referenceParent.processOutput.outputDatasets.length) {
productLoopBody();
} else {
callBack(global.DEFAULT_OK_RESPONSE);
@@ -729,7 +713,7 @@
}
function writeDataRange(pBegin, pEnd, pProductFolder, callBack) {
function writeDataRange(pBegin, pEnd, productCodeName, callBack) {
try {
@@ -743,7 +727,7 @@
let fileContent = JSON.stringify(dataRange);
let fileName = '/Data.Range.' + market.assetA + '_' + market.assetB + '.json';
let filePath = bot.filePathRoot + "/Output/" + pProductFolder + "/" + bot.process + fileName;
let filePath = bot.filePathRoot + "/Output/" + productCodeName + "/" + bot.process + fileName;
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
+29 -31
View File
@@ -1,4 +1,4 @@
exports.newMultiPeriodMarket = function newMultiPeriodMarket(bot, logger, COMMONS, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE) {
exports.newMultiPeriodMarket = function newMultiPeriodMarket(bot, logger, UTILITIES, FILE_STORAGE) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
@@ -14,19 +14,16 @@
let statusDependencies;
let dataDependencies;
let storages = [];
let dataFiles = [];
let datasets = [];
let dataFiles = new Map();
let usertBot;
const FILE_STORAGE = require('./FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage(logger);
let botInstance;
let processConfig;
return thisObject;
function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, pAssistant, callBackFunction) {
function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, callBackFunction) {
try {
@@ -39,11 +36,11 @@
dataDependencies = pDataDependencies;
processConfig = pProcessConfig;
for (let i = 0; i < dataDependencies.config.length; i++) {
for (let i = 0; i < dataDependencies.nodeArray.length; i++) {
let key;
let storage;
let dependency = dataDependencies.config[i];
let dataset;
let dependency = dataDependencies.nodeArray[i];
key = dependency.devTeam + "-" +
dependency.bot + "-" +
@@ -51,14 +48,16 @@
dependency.dataSet + "-" +
dependency.dataSetVersion
storage = dataDependencies.dataSets.get(key);
dataset = dataDependencies.dataSets.get(key);
storages.push(storage);
datasets.push(dataset);
}
usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, fileStorage);
usertBot.initialize(dataDependencies, callBackFunction, pAssistant);
let USER_BOT_MODULE = require("./IndicatorBot")
botInstance = USER_BOT_MODULE.newIndicatorBot(bot, logger, UTILITIES, FILE_STORAGE);
botInstance.initialize(callBackFunction);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
@@ -67,12 +66,11 @@
}
function finalize() {
storages = undefined
datasets = undefined
dataFiles = undefined
statusDependencies = undefined
dataDependencies = undefined
usertBot = undefined
fileStorage = undefined
botInstance = undefined
processConfig = undefined
thisObject = undefined
}
@@ -150,10 +148,10 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Entering function."); }
const timePeriod = global.marketFilesPeriods[n][0];
const outputPeriodLabel = global.marketFilesPeriods[n][1];
const timePeriodLabel = global.marketFilesPeriods[n][1];
let dependencyIndex = 0;
dataFiles = [];
dataFiles = new Map;
dependencyLoopBody();
@@ -163,8 +161,8 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> Entering function."); }
let dependency = dataDependencies.config[dependencyIndex];
let storage = storages[dependencyIndex];
let dependency = dataDependencies.nodeArray[dependencyIndex];
let dataset = datasets[dependencyIndex];
getFile();
@@ -179,11 +177,11 @@
let filePath
if (dependency.dataSet === "Multi-Period-Market") {
filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel;
filePath = dependency.product + '/' + dependency.dataSet + "/" + timePeriodLabel;
} else {
filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath;
}
storage.getTextFile(filePath, fileName, onFileReceived);
dataset.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
@@ -200,7 +198,7 @@
}
let dataFile = JSON.parse(text);
dataFiles.push(dataFile);
dataFiles.set(dependency.id, dataFile);
dependencyControlLoop();
@@ -232,7 +230,7 @@
dependencyIndex++;
if (dependencyIndex < dataDependencies.config.length) {
if (dependencyIndex < dataDependencies.nodeArray.length) {
dependencyLoopBody();
@@ -255,14 +253,14 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> Entering function."); }
const timePeriod = global.marketFilesPeriods[n][0];
const outputPeriodLabel = global.marketFilesPeriods[n][1];
const timePeriodLabel = global.marketFilesPeriods[n][1];
usertBot.start(
botInstance.start(
dataFiles,
timePeriod,
outputPeriodLabel,
contextVariables.dateBeginOfMarket,
contextVariables.dateEndOfMarket,
timePeriodLabel,
undefined,
undefined,
onBotFinished);
function onBotFinished(err) {
+170
View File
@@ -0,0 +1,170 @@
exports.newProcessExecutionEvents = function newProcessExecutionEvents(BOT, logger) {
/*
Here we manage the process execution events. This allow us to emit events when the process starts and finishes. Also to wait for a dependent event
of another process.
*/
const MODULE_NAME = "Process Execution Events";
let bot = BOT;
let thisObject = {
initialize, initialize,
start: start,
finish: finish
};
let processThisDependsOn; // This is the process this process needs to wait for it to finishes in order to start.
let month;
let year;
let currentProcessKey
let datetimeForLogs = ''
return thisObject;
function initialize(pMonth, pYear, callBackFunction) {
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
month = pMonth;
year = pYear;
if (month && year) {
datetimeForLogs = "Month: " + month + " Year: " + year
}
let name = 'Not Depends on any Process'
if (bot.processNode.referenceParent !== undefined) {
currentProcessKey = bot.processNode.referenceParent.name + "-" + bot.processNode.referenceParent.type + "-" + bot.processNode.referenceParent.id
if (bot.processNode.referenceParent.executionStartedEvent !== undefined) {
if (bot.processNode.referenceParent.executionStartedEvent.referenceParent !== undefined) {
if (bot.processNode.referenceParent.executionStartedEvent.referenceParent.parentNode !== undefined) {
processThisDependsOn = bot.processNode.referenceParent.executionStartedEvent.referenceParent.parentNode
name = processThisDependsOn.name
if (processThisDependsOn.code.monthlyInstances === true) {
logger.fileName = MODULE_NAME + "." + name + "." + year + "." + month;
}
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> " + currentProcessKey + datetimeForLogs + " depends on " + name); }
}
}
}
}
logger.fileName = MODULE_NAME + "." + name;
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function start(callBackFunction) {
try {
if (processThisDependsOn !== undefined) {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> waitForDependantProcess -> Entering Code Block."); }
/* This forces this process to wait until the process that this one depends on, emits its event signaling that the process execution has finished. */
let extraCallerId = '-' + Math.trunc(Math.random() * 10000) + '-'
if (month) { extraCallerId = extraCallerId + '-' + month }
if (year) { extraCallerId = extraCallerId + '-' + year }
let key = processThisDependsOn.name + "-" + processThisDependsOn.type + "-" + processThisDependsOn.id
let callerId = bot.devTeam + "-" + bot.codeName + "-" + bot.process + extraCallerId
let subscriptionId
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> waitForDependantProcess -> started listening to Process Execution Finished. "); }
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> waitForDependantProcess -> key = " + key); }
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> waitForDependantProcess -> callerId = " + callerId); }
global.SYSTEM_EVENT_HANDLER.listenToEvent(key, 'Process Execution Finished', undefined, callerId, responseCallBack, eventsCallBack)
function responseCallBack(message) {
if (message.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> responseCallBack -> message = " + JSON.stringify(message))
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
} else {
subscriptionId = message.eventSubscriptionId
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> waitForDependantProcess -> subscriptionId = " + subscriptionId); }
}
}
function eventsCallBack(message) {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> Entering function."); }
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> message = " + JSON.stringify(message)); }
/* We continue the normal flow after we learn the dependent process has finished its execution. */
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> stopListening to Process Execution Finished. "); }
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> subscriptionId = " + subscriptionId); }
global.SYSTEM_EVENT_HANDLER.stopListening(key, 'Process Execution Finished', subscriptionId)
if (message.event.err.result === global.DEFAULT_OK_RESPONSE.result) {
/* We emit our own event that the process started. */
let event = {
err: global.DEFAULT_OK_RESPONSE
}
global.SYSTEM_EVENT_HANDLER.createEventHandler(currentProcessKey, 'Process Execution Started')
global.SYSTEM_EVENT_HANDLER.raiseEvent(currentProcessKey, 'Process Execution Started', event)
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> " + currentProcessKey + " Process Execution Started because " + key + datetimeForLogs + " Finished."); }
}
callBackFunction(message.event.err);
}
} else {
/* In this case, the Process does not depends on a process which needs to wait for. */
/* We emit our own event that the process started. */
let event = {
err: global.DEFAULT_OK_RESPONSE
}
global.SYSTEM_EVENT_HANDLER.createEventHandler(currentProcessKey, 'Process Execution Started')
global.SYSTEM_EVENT_HANDLER.raiseEvent(currentProcessKey, 'Process Execution Started', event)
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> " + currentProcessKey + " Process Execution Started " + datetimeForLogs); }
callBackFunction(global.DEFAULT_OK_RESPONSE);
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function finish(callBackFunction) {
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] finish -> Entering function."); }
let event = {
err: global.DEFAULT_OK_RESPONSE
}
global.SYSTEM_EVENT_HANDLER.createEventHandler(currentProcessKey, 'Process Execution Finished')
global.SYSTEM_EVENT_HANDLER.raiseEvent(currentProcessKey, 'Process Execution Finished', event)
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] finish -> " + currentProcessKey + " Process Execution Finished " + datetimeForLogs); }
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] finish -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
};
+104
View File
@@ -0,0 +1,104 @@
exports.newProcessOutput = function newProcessOutput(BOT, logger) {
/*
Here we emit the events that signals that a Dataset was updated.
*/
const MODULE_NAME = "Process Output";
let bot = BOT;
let thisObject = {
raiseEvents, raiseEvents
};
return thisObject;
function raiseEvents(statusDependencies, callBackFunction) {
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] raiseEvents -> Entering function."); }
/* We will reaise the events for the datasets impacted by the process that just finished. */
if (bot.processNode.referenceParent.processOutput !== undefined) {
if (bot.processNode.referenceParent.processOutput.outputDatasets !== undefined) {
let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets
for (let j = 0; j < outputDatasets.length; j++) {
let outputDataset = outputDatasets[j]
/* Some validations to verify that everything is in place. */
if (outputDataset.referenceParent !== undefined) {
if (outputDataset.referenceParent.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> codeName at Dataset Definition not defined. Dataset Definition = " + JSON.stringify(outputDataset.referenceParent));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDataset.referenceParent.parentNode !== undefined) {
if (outputDataset.referenceParent.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> codeName at Product not defined. Product = " + JSON.stringify(outputDataset.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDataset.referenceParent.parentNode.parentNode !== undefined) {
if (outputDataset.referenceParent.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> codeName at Bot not defined. Bot = " + JSON.stringify(outputDataset.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (outputDataset.referenceParent.parentNode.parentNode.parentNode !== undefined) {
if (outputDataset.referenceParent.parentNode.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> codeName at Team not defined. Team = " + JSON.stringify(outputDataset.referenceParent.parentNode.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
} else {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> Bot not attached to a Team. Bot = " + JSON.stringify(outputDataset.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
} else {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> Product not attached to a Bot. Product = " + JSON.stringify(outputDataset.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
} else {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> Dataset Definition not attached to a Product. Dataset Definition = " + JSON.stringify(outputDataset.referenceParent));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
} else {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> Output Dataset with no reference to a Dataset Definition. Output Dataset = " + JSON.stringify(outputDataset));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
/* All good, lets emit the event. */
let devTeam = outputDataset.referenceParent.parentNode.parentNode.parentNode.code.codeName
let botName = outputDataset.referenceParent.parentNode.parentNode.code.codeName
let product = outputDataset.referenceParent.parentNode.code.codeName
let dataset = outputDataset.referenceParent.code.codeName
let statusReport = statusDependencies.reportsByMainUtility.get("Self Reference")
key = devTeam + "-" + botName + "-" + product + "-" + dataset
let event = {
lastFile: statusReport.file.lastFile
}
global.SYSTEM_EVENT_HANDLER.createEventHandler(key, 'Dataset Updated')
global.SYSTEM_EVENT_HANDLER.raiseEvent(key, 'Dataset Updated', event)
}
}
}
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
};
+17 -1
View File
@@ -25,6 +25,10 @@
<Compile Include="Assistant.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Commons.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="IndicatorBot.js" />
<Compile Include="Integrations\Ecosystem.js" />
<Compile Include="FileStorage.js" />
<Compile Include="MultiPeriod.js">
@@ -36,10 +40,22 @@
<Compile Include="MultiPeriodMarket.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="ProcessExecutionEvents.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="ProcessOutput.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Session.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TradingEngineProcessMainLoop.js">
<Compile Include="TradingBot.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TradingBotProcessMainLoop.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TradingSimulation.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="utils\logger.js">
+300 -278
View File
@@ -79,7 +79,7 @@
logContent: false,
intensiveLogging: false
},
"Data Set": {
"Dataset": {
logInfo: true,
logWarnings: false,
logErrors: true,
@@ -92,6 +92,20 @@
logErrors: true,
logContent: false,
intensiveLogging: false
},
"Process Execution Events": {
logInfo: true,
logWarnings: false,
logErrors: true,
logContent: false,
intensiveLogging: false
},
"Process Output": {
logInfo: true,
logWarnings: false,
logErrors: true,
logContent: false,
intensiveLogging: false
}
};
@@ -121,292 +135,300 @@
const INDICATOR_BOT_MAIN_LOOP_MODULE = require('./IndicatorBotProcessMainLoop');
const SENSOR_BOT_MAIN_LOOP_MODULE = require('./SensorBotProcessMainLoop');
const TRADING_ENGINE_MAIN_LOOP_MODULE = require('./TradingEngineProcessMainLoop');
/* Loop through all the processes configured to be run by this Node.js Instance. */
/* Now we will read the config of the bot from the path we obtained at the Task Server config. */
const TRADING_ENGINE_MAIN_LOOP_MODULE = require('./TradingBotProcessMainLoop');
let botConfig;
let processInstance = global.TASK_NODE.bot.processes[processIndex]
getBotConfig();
/* Here we will check if we need to load the configuration and code of the bot from a file or we will take that from the UI. */
if (
processInstance.referenceParent.code.framework !== undefined &&
( processInstance.referenceParent.code.framework.name === 'Multi-Period-Market' ||
processInstance.referenceParent.code.framework.name === 'Multi-Period-Daily' ||
processInstance.referenceParent.code.framework.name === 'Multi-Period')
) {
botConfig = processInstance.referenceParent.parentNode.code
botConfig.definedByUI = true
bootingBot(processIndex)
return
} else {
getBotConfigFromFile();
return
}
function getBotConfig() {
function getBotConfigFromFile() {
try {
console.log(logDisplace + "Root : [INFO] start -> getBotConfig -> Entering function. ");
console.log(logDisplace + "Root : [INFO] start -> getBotConfigFromFile -> Entering function. ");
const FILE_STORAGE = require('./FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage();
let filePath = global.TASK_NODE.bot.code.team + '/bots/' + global.TASK_NODE.bot.code.repo + '/this.bot.config.json';
let filePath = global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName + '/bots/' + global.TASK_NODE.bot.code.repo + '/this.bot.config.json';
fileStorage.getTextFile(global.TASK_NODE.bot.code.team, filePath, onFileReceived);
fileStorage.getTextFile(global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName, filePath, onFileReceived);
function onFileReceived(err, text) {
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> err = " + JSON.stringify(err));
console.log(logDisplace + "Root : [ERROR] start -> getBotConfigFromFile -> onInizialized -> onFileReceived -> err = " + JSON.stringify(err));
console.log(logDisplace + "Root : [ERROR] start -> getBotConfigFromFile -> onInizialized -> onFileReceived -> filePath = " + filePath);
console.log(logDisplace + "Root : [ERROR] start -> getBotConfigFromFile -> onInizialized -> onFileReceived -> team = " + global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName);
return;
}
try {
botConfig = JSON.parse(text);
botConfig.repo = global.TASK_NODE.bot.code.repo;
findProcess(processIndex);
bootingBot(processIndex);
} catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> onInizialized -> onFileReceived -> err = " + JSON.stringify(err));
console.log(logDisplace + "Root : [ERROR] start -> getBotConfigFromFile -> onInizialized -> onFileReceived -> err = " + JSON.stringify(err));
return;
}
}
}
catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> getBotConfig -> err = " + err.stack);
console.log(logDisplace + "Root : [ERROR] start -> getBotConfigFromFile -> err = " + err.stack);
return;
}
}
function findProcess(processIndex) {
function bootingBot(processIndex) {
try {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Entering function. "); }
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> bootingBot -> Entering function. "); }
botConfig.process = global.TASK_NODE.bot.processes[processIndex].code.process;
botConfig.process = global.TASK_NODE.bot.processes[processIndex].referenceParent.code.codeName
botConfig.debug = {};
botConfig.processIndex = processIndex
botConfig.processNode = global.TASK_NODE.bot.processes[processIndex]
/* Loop Counter */
/* Logs Mantainance Stuff */
botConfig.LOGS_TO_DELETE_QUEUE = []
botConfig.DELETE_QUEUE_SIZE = 10 // This number represents how many log files can be at the queue at any point in time, which means how many logs are not still deleted.
botConfig.loopCounter = 0;
/* Simplifying the access to basic info */
botConfig.devTeam = global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName
/* This stuff is still hardcoded and unresolved. */
botConfig.version = {
"major": 1,
"minor": 0
}
botConfig.dataSetVersion = "dataSet.V1"
/* Loop Counter */
botConfig.loopCounter = 0;
/* File Path Root */
botConfig.filePathRoot = botConfig.devTeam + "/" + botConfig.codeName + "." + botConfig.version.major + "." + botConfig.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion;
/* Process Key */
botConfig.processKey = global.TASK_NODE.bot.processes[processIndex].name + '-' + global.TASK_NODE.bot.processes[processIndex].type + '-' + global.TASK_NODE.bot.processes[processIndex].id
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> filePathRoot = " + botConfig.filePathRoot); }
/* Bot Type */
botConfig.type = global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.type
/* Now we loop throug all the configured processes at each bots configuration until we find the one we are supposed to run at this Node.js process. */
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> bootingBot -> filePathRoot = " + botConfig.filePathRoot); }
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> bootingBot -> Process found at the bot configuration file. -> process = " + global.TASK_NODE.bot.processes[processIndex].referenceParent.code.codeName); }
let processFound = false;
let processConfig = global.TASK_NODE.bot.processes[processIndex].referenceParent.code
for (let i = 0; i < botConfig.processes.length; i++) {
if (botConfig.processes[i].name === global.TASK_NODE.bot.processes[processIndex].code.process) {
processFound = true;
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> process = " + global.TASK_NODE.bot.processes[processIndex].code.process); }
let processConfig = botConfig.processes[i];
if (processConfig.framework !== undefined) {
if (processConfig.framework.name === "Multi-Period-Daily" || processConfig.framework.name === "Multi-Period-Market" || processConfig.framework.name === "Multi-Period") {
processConfig.framework.startDate.resumeExecution = true;
if (processConfig.startMode.noTime !== undefined) {
if (processConfig.startMode.noTime.run === "true") {
if (processConfig.startMode.noTime.beginDatetime !== undefined) {
processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime;
processConfig.framework.startDate.resumeExecution = true;
}
}
}
if (processConfig.startMode.userDefined !== undefined) {
if (processConfig.startMode.userDefined.run === "true") {
if (processConfig.startMode.userDefined.beginDatetime !== undefined) {
processConfig.framework.startDate.fixedDate = processConfig.startMode.userDefined.beginDatetime;
processConfig.framework.startDate.resumeExecution = processConfig.startMode.userDefined.resumeExecution;
}
}
if (processConfig.framework !== undefined) {
if (processConfig.framework.name === "Multi-Period-Daily" || processConfig.framework.name === "Multi-Period-Market" || processConfig.framework.name === "Multi-Period") {
processConfig.framework.startDate.resumeExecution = true;
if (processConfig.startMode.noTime !== undefined) {
if (processConfig.startMode.noTime.run === "true") {
if (processConfig.startMode.noTime.beginDatetime !== undefined) {
processConfig.framework.startDate.fixedDate = processConfig.startMode.noTime.beginDatetime;
processConfig.framework.startDate.resumeExecution = true;
}
}
}
try {
/* We test each type of start Mode to get what to run and how. */
if (processConfig.startMode.allMonths !== undefined) {
if (processConfig.startMode.allMonths.run === "true") {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> allMonths start mode detected. "); }
for (let year = processConfig.startMode.allMonths.maxYear; year >= processConfig.startMode.allMonths.minYear; year--) {
for (let month = 12; month > 0; month--) {
let padMonth = pad(month, 2)
let newInstanceBotConfig = JSON.parse(JSON.stringify(botConfig));
newInstanceBotConfig.debug = {
month: pad(month, 2),
year: pad(year, 4)
};
let timeDelay = Math.random() * 10 * 1000; // We introduce a short delay so as to not overload the machine.
setTimeout(startProcess, timeDelay);
function startProcess() {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> startProcess -> Ready to start process."); }
switch (botConfig.type) {
case 'Sensor': {
runSensorBot(newInstanceBotConfig, processConfig, padMonth, year);
break;
}
case 'Indicator': {
runIndicatorBot(newInstanceBotConfig, processConfig, padMonth, year);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
}
if (processConfig.startMode.userDefined !== undefined) {
if (processConfig.startMode.userDefined.run === "true") {
if (processConfig.startMode.userDefined.beginDatetime !== undefined) {
processConfig.framework.startDate.fixedDate = processConfig.startMode.userDefined.beginDatetime;
processConfig.framework.startDate.resumeExecution = processConfig.startMode.userDefined.resumeExecution;
}
}
if (processConfig.startMode.oneMonth !== undefined) {
if (processConfig.startMode.oneMonth.run === "true") {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> oneMonth start mode detected. "); }
startProcess();
function startProcess() {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> startProcess -> Ready to start process."); }
let month = pad(processConfig.startMode.oneMonth.month, 2);
let year = processConfig.startMode.oneMonth.year;
botConfig.debug = {
month: pad(month, 2),
year: pad(year, 4)
};
switch (botConfig.type) {
case 'Sensor': {
runSensorBot(botConfig, processConfig, month, year);
break;
}
case 'Indicator': {
runIndicatorBot(botConfig, processConfig, month, year);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
}
if (processConfig.startMode.noTime !== undefined) {
if (processConfig.startMode.noTime.run === "true") {
let month = pad((new Date()).getUTCMonth() + 1, 2);
let year = (new Date()).getUTCFullYear();
if (processConfig.startMode.noTime.resumeExecution === true) {
botConfig.hasTheBotJustStarted = false;
} else {
botConfig.hasTheBotJustStarted = true;
}
switch (botConfig.type) {
case 'Sensor': {
runSensorBot(botConfig, processConfig, month, year);
break;
}
case 'Indicator': {
runIndicatorBot(botConfig, processConfig, month, year);
break;
}
case 'Trading Engine': {
runTradingEngine(botConfig, processConfig);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
if (processConfig.startMode.fixedInterval !== undefined) {
if (processConfig.startMode.fixedInterval.run === "true") {
botConfig.runAtFixedInterval = true;
botConfig.fixedInterval = processConfig.startMode.fixedInterval.interval;
let month = pad((new Date()).getUTCMonth() + 1, 2);
let year = (new Date()).getUTCFullYear();
switch (botConfig.type) {
case 'Sensor': {
runSensorBot(botConfig, processConfig, month, year);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
if (processConfig.startMode.userDefined !== undefined) {
if (processConfig.startMode.userDefined.run === "true") {
botConfig.startMode = "User Defined";
console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode);
let month = pad((new Date()).getUTCMonth() + 1, 2);
let year = (new Date()).getUTCFullYear();
if (processConfig.startMode.userDefined.resumeExecution === true) {
botConfig.hasTheBotJustStarted = false;
} else {
botConfig.hasTheBotJustStarted = true;
}
switch (botConfig.type) {
case 'Trading Engine': {
runTradingEngine(botConfig, processConfig);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
} catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected exception. -> err = " + err.stack);
}
}
}
if (processFound === false) {
try {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Process listed at the configuration file of Task Server not found at the configuration file of the bot.");
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> process = " + global.TASK_NODE.bot.processes[processIndex].code.process);
/* We test each type of start Mode to get what to run and how. */
if (processConfig.startMode.allMonths !== undefined) {
if (processConfig.startMode.allMonths.run === "true") {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> bootingBot -> allMonths start mode detected. "); }
for (let year = processConfig.startMode.allMonths.maxYear; year >= processConfig.startMode.allMonths.minYear; year--) {
for (let month = 12; month > 0; month--) {
let padMonth = pad(month, 2)
let newInstanceBotConfig = JSON.parse(JSON.stringify(botConfig));
newInstanceBotConfig.debug = {
month: pad(month, 2),
year: pad(year, 4)
};
let timeDelay = Math.random() * 10 * 1000; // We introduce a short delay so as to not overload the machine.
setTimeout(startProcess, timeDelay);
function startProcess() {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> bootingBot -> startProcess -> Ready to start process."); }
switch (botConfig.type) {
case 'Sensor Bot': {
runSensorBot(newInstanceBotConfig, processConfig, padMonth, year);
break;
}
case 'Indicator Bot': {
runIndicatorBot(newInstanceBotConfig, processConfig, padMonth, year);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
}
}
}
if (processConfig.startMode.oneMonth !== undefined) {
if (processConfig.startMode.oneMonth.run === "true") {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> bootingBot -> oneMonth start mode detected. "); }
startProcess();
function startProcess() {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> bootingBot -> startProcess -> Ready to start process."); }
let month = pad(processConfig.startMode.oneMonth.month, 2);
let year = processConfig.startMode.oneMonth.year;
botConfig.debug = {
month: pad(month, 2),
year: pad(year, 4)
};
switch (botConfig.type) {
case 'Sensor Bot': {
runSensorBot(botConfig, processConfig, month, year);
break;
}
case 'Indicator Bot': {
runIndicatorBot(botConfig, processConfig, month, year);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> startProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
}
if (processConfig.startMode.noTime !== undefined) {
if (processConfig.startMode.noTime.run === "true") {
let month = pad((new Date()).getUTCMonth() + 1, 2);
let year = (new Date()).getUTCFullYear();
if (processConfig.startMode.noTime.resumeExecution === true) {
botConfig.hasTheBotJustStarted = false;
} else {
botConfig.hasTheBotJustStarted = true;
}
switch (botConfig.type) {
case 'Sensor Bot': {
runSensorBot(botConfig, processConfig, month, year);
break;
}
case 'Indicator Bot': {
runIndicatorBot(botConfig, processConfig, month, year);
break;
}
case 'Trading Bot': {
runTradingBot(botConfig, processConfig);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
if (processConfig.startMode.fixedInterval !== undefined) {
if (processConfig.startMode.fixedInterval.run === "true") {
botConfig.runAtFixedInterval = true;
botConfig.fixedInterval = processConfig.startMode.fixedInterval.interval;
let month = pad((new Date()).getUTCMonth() + 1, 2);
let year = (new Date()).getUTCFullYear();
switch (botConfig.type) {
case 'Sensor Bot': {
runSensorBot(botConfig, processConfig, month, year);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
if (processConfig.startMode.userDefined !== undefined) {
if (processConfig.startMode.userDefined.run === "true") {
botConfig.startMode = "User Defined";
console.log(logDisplace + "Root : [INFO] start -> bootingBot -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode);
let month = pad((new Date()).getUTCMonth() + 1, 2);
let year = (new Date()).getUTCFullYear();
if (processConfig.startMode.userDefined.resumeExecution === true) {
botConfig.hasTheBotJustStarted = false;
} else {
botConfig.hasTheBotJustStarted = true;
}
switch (botConfig.type) {
case 'Trading Bot': {
runTradingBot(botConfig, processConfig);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
}
} catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> Unexpected exception. -> err = " + err.stack);
}
function runSensorBot(pBotConfig, pProcessConfig, pMonth, pYear) {
try {
@@ -418,9 +440,9 @@
logger = DEBUG_MODULE.newDebugLog();
logger.bot = pBotConfig;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> Entering function."); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> pMonth = " + pMonth); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> pYear = " + pYear); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runSensorBot -> Entering function."); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runSensorBot -> pMonth = " + pMonth); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runSensorBot -> pYear = " + pYear); }
let extractionBotMainLoop = SENSOR_BOT_MAIN_LOOP_MODULE.newSensorBotProcessMainLoop(pBotConfig, logger);
extractionBotMainLoop.initialize(pProcessConfig, onInitializeReady);
@@ -444,31 +466,31 @@
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [INFO] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
console.log(logDisplace + "Root : [INFO] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [INFO] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.persist();
} else {
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. ");
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bye.");
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. ");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bye.");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution was aborted.");
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot execution was aborted.");
logger.persist();
}
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
} else {
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> Bot will not be started. ");
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> Bot will not be started. ");
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runSensorBot -> onInitializeReady -> err = " + err.message);
logger.persist();
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
@@ -476,7 +498,7 @@
}
}
catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> err = " + err.stack);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runSensorBot -> err = " + err.stack);
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
@@ -492,9 +514,9 @@
logger = DEBUG_MODULE.newDebugLog();
logger.bot = pBotConfig;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> Entering function."); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> pMonth = " + pMonth); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> pYear = " + pYear); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> Entering function."); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> pMonth = " + pMonth); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> pYear = " + pYear); }
let indicatorBotMainLoop = INDICATOR_BOT_MAIN_LOOP_MODULE.newIndicatorBotProcessMainLoop(pBotConfig, logger);
indicatorBotMainLoop.initialize(pProcessConfig, onInitializeReady);
@@ -518,41 +540,41 @@
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [INFO] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
console.log(logDisplace + "Root : [INFO] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [INFO] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.persist();
} else {
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. ");
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bye.");
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs.");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. ");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bye.");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs.");
logger.persist();
}
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
} else {
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot. ");
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot. ");
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> err = " + err.message);
logger.persist();
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
}
catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> err = " + err.stack);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runIndicatorBot -> err = " + err.stack);
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
function runTradingEngine(pBotConfig, pProcessConfig) {
function runTradingBot(pBotConfig, pProcessConfig) {
global.TOTAL_PROCESS_INSTANCES_CREATED++
@@ -563,16 +585,16 @@
logger = DEBUG_MODULE.newDebugLog();
logger.bot = pBotConfig;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingEngine -> Entering function."); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runTradingBot -> Entering function."); }
let tradingEngineMainLoop = TRADING_ENGINE_MAIN_LOOP_MODULE.newTradingEngineProcessMainLoop(pBotConfig, logger);
tradingEngineMainLoop.initialize(pProcessConfig, onInitializeReady);
let tradingBotMainLoop = TRADING_ENGINE_MAIN_LOOP_MODULE.newTradingBotProcessMainLoop(pBotConfig, logger);
tradingBotMainLoop.initialize(pProcessConfig, onInitializeReady);
function onInitializeReady(err) {
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
tradingEngineMainLoop.run(whenRunFinishes);
tradingBotMainLoop.run(whenRunFinishes);
function whenRunFinishes(err) {
@@ -584,42 +606,42 @@
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
console.log(logDisplace + "Root : [INFO] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId);
console.log(logDisplace + "Root : [INFO] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.persist();
} else {
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. ");
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bye.");
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs.");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. ");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bye.");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs.");
logger.persist();
}
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
} else {
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> Failed to initialize the bot. ");
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> Failed to initialize the bot. ");
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runTradingBot -> onInitializeReady -> err = " + err.message);
logger.persist();
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
}
catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingEngine -> err = " + err.stack);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runTradingBot -> err = " + err.stack);
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
}
catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> err = " + err.stack);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> err = " + err.stack);
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
+313 -6
View File
@@ -35,7 +35,13 @@
processConfig = pProcessConfig;
let filePath = bot.devTeam + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name;
if (bot.definedByUI === true) {
/* The code of the bot is defined at the UI. No need to load a file with the code. */
callBackFunction(global.DEFAULT_OK_RESPONSE);
return
}
let filePath = bot.devTeam + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.codeName
filePath += "/User.Bot.js"
fileStorage.getTextFile(bot.devTeam, filePath, onBotDownloaded);
@@ -45,6 +51,7 @@
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> err = " + err.message);
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> filePath = " + filePath);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
@@ -130,6 +137,8 @@
const STATUS_REPORT = require(ROOT_DIR + 'StatusReport');
const EXCHANGE_API = require('@superalgos/exchange-gateway');
const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies');
const PROCESS_EXECUTION_EVENTS = require(ROOT_DIR + 'ProcessExecutionEvents');
const PROCESS_OUTPUT = require(ROOT_DIR + 'ProcessOutput');
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
@@ -140,15 +149,165 @@
console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4)
+ " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8) + " bot.processDatetime = " + bot.processDatetime.toISOString());
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
/* We will prepare first the infraestructure needed for the bot to run. There are 4 modules we need to sucessfullly initialize first. */
let processOutput
let processExecutionEvents
let userBot;
let statusDependencies;
let exchangeAPI;
let nextWaitTime;
initializeStatusDependencies();
initializeProcessExecutionEvents();
function initializeProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> Entering function."); }
processExecutionEvents = PROCESS_EXECUTION_EVENTS.newProcessExecutionEvents(bot, logger)
processExecutionEvents.initialize(pMonth, pYear, onInizialized);
function onInizialized(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Execution finished well.");
startProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function startProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> Entering function."); }
processExecutionEvents.start(onStarted);
function onStarted(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Execution finished well.");
initializeStatusDependencies();
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessExecutionEvents -> onStarted -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function initializeStatusDependencies() {
@@ -158,7 +317,7 @@
statusDependencies = STATUS_DEPENDENCIES.newStatusDependencies(bot, logger, STATUS_REPORT, UTILITIES);
statusDependencies.initialize(processConfig.statusDependencies, pMonth, pYear, onInizialized);
statusDependencies.initialize(pMonth, pYear, onInizialized);
function onInizialized(err) {
@@ -427,8 +586,7 @@
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> onFinished > Execution finished well.");
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
raiseEventsProcessOutput()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
@@ -541,6 +699,155 @@
}
}
function raiseEventsProcessOutput() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> Entering function."); }
processOutput = PROCESS_OUTPUT.newProcessOutput(bot, logger)
processOutput.raiseEvents(statusDependencies, onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> onFinished -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> onFinished -> Execution finished well.");
finishProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> raiseEventsProcessOutput -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function finishProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> Entering function."); }
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Execution finished well.");
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> finishProcessExecutionEvents -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function loopControl(nextWaitTime) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Entering function."); }
+4 -4
View File
@@ -44,7 +44,7 @@
return
function runSession(message) {
/* We are going to run the Definition comming at the event. */
bot.DEFINITION = JSON.parse(message.event.definition)
bot.SESSION = JSON.parse(message.event.session)
@@ -491,9 +491,9 @@
if (socialBot.type === code.botType && socialBot.id === code.botId) {
if (socialBot.type === "Telegram Bot") {
if (announcement.formulaValue !== undefined) {
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, announcement.formulaValue)
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, announcement.formulaValue).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> setUpSocialBots -> announce -> Telegram API error -> err = " + err))
} else {
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, code.text)
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, code.text).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> setUpSocialBots -> announce -> Telegram API error -> err = " + err))
}
}
}
@@ -523,7 +523,7 @@
const Telegram = require('telegraf/telegram')
let telegramAPI
telegramAPI = new Telegram(botToken)
telegramAPI.sendMessage(chatId, bot.SESSION.type + " '" + bot.SESSION.name + "' was Started.")
telegramAPI.sendMessage(chatId, bot.SESSION.type + " '" + bot.SESSION.name + "' was Started.").catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> setUpTelegramBot -> Telegram API error -> err = " + err))
let botInstance = {
telegramBot: telegramBot,
+61 -20
View File
@@ -2,40 +2,78 @@
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
const MODULE_NAME = "Status Dependencies";
let bot = BOT
let thisObject = {
config: undefined,
nodeArray: undefined,
statusReports: new Map(),
reportsByMainUtility: new Map(),
initialize: initialize,
keys: []
};
return thisObject;
function initialize(pStatusDependenciesConfig, pMonth, pYear, callBackFunction) {
function initialize(pMonth, pYear, callBackFunction) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
thisObject.config = pStatusDependenciesConfig;
/* Basic Valdidations */
if (bot.processNode.referenceParent.processDependencies !== undefined) {
if (bot.processNode.referenceParent.processDependencies.statusDependencies !== undefined) {
thisObject.nodeArray = bot.processNode.referenceParent.processDependencies.statusDependencies
} else {
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> It is not possible to not have status dependencies at all.");
callBackFunction(global.DEFAULT_OK_RESPONSE)
return
}
} else {
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> It is not possible to not have process dependencies, which means not status dependencies.");
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
return
}
/*
/*For each dependency we will initialize the status report, and load it as part of this initialization process.*/
For each dependency declared at the bot config, we will initialize the status report, and load it as part of this initialization process.
*/
let alreadyCalledBack = false;
let loadCount = 0;
let dependenciesToProcess = []
for (let i = 0; i < thisObject.nodeArray.length; i++) {
let statusDependency = {
dependency: thisObject.nodeArray[i],
month: pMonth,
year: pYear
}
dependenciesToProcess.push(statusDependency)
for (let i = 0; i < pStatusDependenciesConfig.length; i++) {
/*
For the special case that the statusDependency is a Self Reference AND this process is sliced in different
instances for each month, we will add the main self reference status report that is month/year independent.
*/
if (statusDependency.dependency.code.mainUtility === "Self Reference" && pMonth !== undefined && pYear !== undefined) {
let mainDependency = {
dependency: thisObject.nodeArray[i],
month: undefined,
year: undefined
}
dependenciesToProcess.push(mainDependency)
}
}
for (let i = 0; i < dependenciesToProcess.length; i++) {
let statusReportModule = STATUS_REPORT.newStatusReport(BOT, logger, UTILITIES);
logger.write(MODULE_NAME, "[INFO] initialize -> onInitilized -> Initializing Status Report # " + (i + 1));
statusReportModule.initialize(pStatusDependenciesConfig[i], pMonth, pYear, onInitilized);
let statusDependency = dependenciesToProcess[i]
statusReportModule.initialize(statusDependency.dependency, statusDependency.month, statusDependency.year, onInitilized);
function onInitilized(err) {
@@ -66,8 +104,7 @@
switch (err.message) {
case global.DEFAULT_OK_RESPONSE.message: {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> onLoad -> Execution finished well. -> bot = " + pStatusDependenciesConfig[i].bot); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> onLoad -> Execution finished well. -> process = " + pStatusDependenciesConfig[i].process); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> onLoad -> Execution finished well. -> Status Dependency = " + JSON.stringify(statusDependency.dependency)) }
addReport();
return;
@@ -75,8 +112,8 @@
case "Status Report was never created.": {
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> err = " + err.stack);
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> Report Not Found. -> bot = " + pStatusDependenciesConfig[i].bot);
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> Report Not Found. -> process = " + pStatusDependenciesConfig[i].process);
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> Report Not Found. -> Status Dependency = " + JSON.stringify(statusDependency.dependency))
addReport();
return;
}
@@ -84,8 +121,8 @@
case "Status Report is corrupt.": {
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> err = " + err.stack);
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> Report Not Found. -> bot = " + pStatusDependenciesConfig[i].bot);
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> Report Not Found. -> process = " + pStatusDependenciesConfig[i].process);
logger.write(MODULE_NAME, "[WARN] initialize -> onLoad -> Report Not Found. -> Status Dependency = " + JSON.stringify(statusDependency.dependency))
addReport();
return;
}
@@ -117,18 +154,22 @@
let key;
if (pStatusDependenciesConfig[i].dataSetSection === "Month") {
key = pStatusDependenciesConfig[i].devTeam + "-" + pStatusDependenciesConfig[i].bot + "-" + pStatusDependenciesConfig[i].process + "-" + pStatusDependenciesConfig[i].dataSetVersion + "-" + pYear + "-" + pMonth;
if (statusDependency.dependency.processRunMonthly === true && statusDependency.month !== undefined && statusDependency.year !== undefined) {
key = statusDependency.dependency.devTeam + "-" + statusDependency.dependency.bot + "-" + statusDependency.dependency.process + "-" + statusDependency.dependency.dataSetVersion + "-" + statusDependency.year + "-" + statusDependency.month;
} else {
key = pStatusDependenciesConfig[i].devTeam + "-" + pStatusDependenciesConfig[i].bot + "-" + pStatusDependenciesConfig[i].process + "-" + pStatusDependenciesConfig[i].dataSetVersion;
key = statusDependency.dependency.devTeam + "-" + statusDependency.dependency.bot + "-" + statusDependency.dependency.process + "-" + statusDependency.dependency.dataSetVersion;
}
thisObject.keys.push(key);
thisObject.statusReports.set(key, statusReportModule);
if (statusReportModule.mainUtility !== undefined) {
thisObject.reportsByMainUtility.set(statusReportModule.mainUtility, statusReportModule)
}
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> addReport -> Report added to Map. -> key = " + key); }
if (loadCount === pStatusDependenciesConfig.length) {
if (loadCount === dependenciesToProcess.length) {
if (alreadyCalledBack === false) {
alreadyCalledBack = true
callBackFunction(global.DEFAULT_OK_RESPONSE);
+95 -78
View File
@@ -13,6 +13,7 @@
let bot = BOT;
let thisObject = {
mainUtility: undefined,
file: undefined, // Here we have the JSON object representing the file content.
initialize: initialize,
load: load,
@@ -21,7 +22,7 @@
verifyMarketComplete: verifyMarketComplete
};
let owner; // This is the bot owner of the Status Report. Only owners can save the report and override the existing content.
let statusDependencyNode;
/* Utilities needed. */
@@ -39,63 +40,103 @@
return thisObject;
function initialize(pOwner, pMonth, pYear, callBackFunction) {
function initialize(pStatusDependencyNode, pMonth, pYear, callBackFunction) {
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
logger.fileName = MODULE_NAME + "." + pOwner.bot + "." + pOwner.process;
statusDependencyNode = pStatusDependencyNode;
logger.fileName = MODULE_NAME + "." + statusDependencyNode.type + "." + statusDependencyNode.name + "." + statusDependencyNode.id;
owner = pOwner;
month = pMonth;
year = pYear;
if (bot.SESSION !== undefined && pOwner.type === "Trading Engine") {
/* Some very basic validations that we have all the information needed. */
if (statusDependencyNode.referenceParent === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Status Dependency without Reference Parent. Status Dependency = " + JSON.stringify(statusDependencyNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (statusDependencyNode.referenceParent.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Status Report not attached to a Process Definition. Status Report = " + JSON.stringify(statusDependencyNode.referenceParent));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (statusDependencyNode.referenceParent.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Process Definition witn no codeName defined. Process Definition = " + JSON.stringify(statusDependencyNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (statusDependencyNode.referenceParent.parentNode.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Process Definition not attached to a Bot. Process Definition = " + JSON.stringify(statusDependencyNode.referenceParent.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (statusDependencyNode.referenceParent.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Bot witn no codeName defined. Bot = " + JSON.stringify(statusDependencyNode.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (statusDependencyNode.referenceParent.parentNode.parentNode.parentNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Bot not attached to a Team. Bot = " + JSON.stringify(statusDependencyNode.referenceParent.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
if (statusDependencyNode.referenceParent.parentNode.parentNode.parentNode.code.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] initialize -> Team witn no codeName defined. Team = " + JSON.stringify(statusDependencyNode.referenceParent.parentNode.parentNode.parentNode));
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
/* Simplifying the access to basic info */
statusDependencyNode.bot = statusDependencyNode.referenceParent.parentNode.parentNode.code.codeName
statusDependencyNode.process = statusDependencyNode.referenceParent.parentNode.code.codeName
statusDependencyNode.type = statusDependencyNode.referenceParent.parentNode.parentNode.type
statusDependencyNode.devTeam = statusDependencyNode.referenceParent.parentNode.parentNode.parentNode.code.codeName
/* Let's see if the process is run monthly or not. */
if (statusDependencyNode.referenceParent.parentNode.code.startMode !== undefined) {
if (statusDependencyNode.referenceParent.parentNode.code.startMode.allMonths !== undefined) {
if (statusDependencyNode.referenceParent.parentNode.code.startMode.oneMonth !== undefined) {
if (statusDependencyNode.referenceParent.parentNode.code.startMode.allMonths.run === "true" || statusDependencyNode.referenceParent.parentNode.code.startMode.oneMonth.run === "true") {
statusDependencyNode.processRunMonthly = true
}
}
}
}
/* We retrieve the report main utility */
if (statusDependencyNode.code !== undefined) {
if (statusDependencyNode.code.mainUtility !== undefined) {
thisObject.mainUtility = statusDependencyNode.code.mainUtility
}
}
/* This stuff is still hardcoded and unresolved. */
statusDependencyNode.botVersion = {
"major": 1,
"minor": 0
}
statusDependencyNode.dataSetVersion = "dataSet.V1"
if (bot.SESSION !== undefined && statusDependencyNode.type === "Trading Bot Instance") {
sessionPath = bot.SESSION.folderName + "/"
}
if (owner.dataSetSection === "Month") {
logger.fileName = MODULE_NAME + "." + pOwner.bot + "." + pOwner.process + "." + year + "." + month;
if (statusDependencyNode.processRunMonthly === true && month !== undefined && year !== undefined) {
logger.fileName = MODULE_NAME + "." + statusDependencyNode.bot + "." + statusDependencyNode.process + "." + year + "." + month;
timePath = "/" + year + "/" + month;
}
if (owner.waitUntilNextUpdate === true) {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> waitUntilNextUpdate -> Entering Code Block."); }
/* This forces this process to wait until the process that this one depends on, updates its status report. */
let extraCallerId = ''
if (pMonth) { extraCallerId = extraCallerId + '-' + pMonth }
if (pYear) { extraCallerId = extraCallerId + '-' + pYear }
let key = owner.devTeam + "-" + owner.bot + "-" + owner.process
let callerId = bot.devTeam + "-" + bot.codeName + "-" + bot.process + extraCallerId
let subscriptionIdStatusReport
global.SYSTEM_EVENT_HANDLER.listenToEvent(key, 'Status Report Updated', undefined, callerId, responseCallBack, eventsCallBack)
function responseCallBack(message) {
if (message.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] initialize -> responseCallBack -> message = " + JSON.stringify(message))
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
} else {
subscriptionIdStatusReport = message.eventSubscriptionId
}
}
function eventsCallBack() {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> eventsCallBack -> Entering function."); }
/* We continue the normal flow after we learn the dependent process has updated its status report. */
global.SYSTEM_EVENT_HANDLER.stopListening(key, 'Status Report Updated', subscriptionIdStatusReport)
callBackFunction(global.DEFAULT_OK_RESPONSE);
}
} else {
/* In this case, the Status Report does not depends on a process which needs to wait for. */
callBackFunction(global.DEFAULT_OK_RESPONSE);
}
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
@@ -112,23 +153,23 @@
let fileName = "Status.Report." + global.MARKET.assetA + '_' + global.MARKET.assetB + ".json";
let filePath;
let ownerId = owner.devTeam + "-" + owner.bot + "-" + owner.botVersion.major + "-" + owner.botVersion.minor + "-" + owner.process + "-" + owner.dataSetVersion;
let ownerId = statusDependencyNode.devTeam + "-" + statusDependencyNode.bot + "-" + statusDependencyNode.botVersion.major + "-" + statusDependencyNode.botVersion.minor + "-" + statusDependencyNode.process + "-" + statusDependencyNode.dataSetVersion;
let botId = bot.devTeam + "-" + bot.codeName + "-" + bot.version.major + "-" + bot.version.minor + "-" + bot.process + "-" + bot.dataSetVersion;
if (ownerId !== botId) {
let rootPath = owner.devTeam + "/" + owner.bot + "." + owner.botVersion.major + "." + owner.botVersion.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + owner.dataSetVersion;
filePath = rootPath + "/Reports/" + sessionPath + owner.process + timePath;
let rootPath = statusDependencyNode.devTeam + "/" + statusDependencyNode.bot + "." + statusDependencyNode.botVersion.major + "." + statusDependencyNode.botVersion.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + statusDependencyNode.dataSetVersion;
filePath = rootPath + "/Reports/" + sessionPath + statusDependencyNode.process + timePath;
} else {
filePath = bot.filePathRoot + "/Reports/" + sessionPath + owner.process + timePath;
filePath = bot.filePathRoot + "/Reports/" + sessionPath + statusDependencyNode.process + timePath;
}
if (owner.type === 'Trading') {
if (statusDependencyNode.type === 'Trading') {
fileName = bot.startMode + "." + fileName;
}
filePath += '/' + fileName
fileStorage.getTextFile(owner.devTeam, filePath, onFileReceived);
fileStorage.getTextFile(statusDependencyNode.devTeam, filePath, onFileReceived);
function onFileReceived(err, text) {
@@ -196,10 +237,10 @@
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] save -> Entering function."); }
let ownerId = owner.devTeam + "-" + owner.bot + "-" + owner.botVersion.major + "-" + owner.botVersion.minor + "-" + owner.process + "-" + owner.dataSetVersion;
let ownerId = statusDependencyNode.devTeam + "-" + statusDependencyNode.bot + "-" + statusDependencyNode.botVersion.major + "-" + statusDependencyNode.botVersion.minor + "-" + statusDependencyNode.process + "-" + statusDependencyNode.dataSetVersion;
let botId = bot.devTeam + "-" + bot.codeName + "-" + bot.version.major + "-" + bot.version.minor + "-" + bot.process + "-" + bot.dataSetVersion;
if (ownerId !== botId && owner.process !== "Context") { // Context is a special case where the report is created by the Context.js module itself.
if (ownerId !== botId && statusDependencyNode.process !== "Context") { // Context is a special case where the report is created by the Context.js module itself.
let customErr = {
result: global.CUSTOM_FAIL_RESPONSE.result,
@@ -211,7 +252,7 @@
}
let fileName = "Status.Report." + global.MARKET.assetA + '_' + global.MARKET.assetB + ".json";
let filePath = bot.filePathRoot + "/Reports/" + sessionPath + owner.process + timePath;
let filePath = bot.filePathRoot + "/Reports/" + sessionPath + statusDependencyNode.process + timePath;
if (bot.type === 'Trading' ) {
fileName = bot.startMode + "." + fileName;
@@ -220,7 +261,7 @@
filePath += '/' + fileName
let fileContent = JSON.stringify(thisObject.file);
fileStorage.createTextFile(owner.devTeam, filePath, fileContent + '\n', onFileCreated);
fileStorage.createTextFile(statusDependencyNode.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
@@ -236,30 +277,6 @@
logger.write(MODULE_NAME, "[INFO] save -> onFileCreated -> Content written = " + fileContent);
}
/* Here we raise the event stating that this status report was updated. */
let key = bot.devTeam + "-" + bot.codeName + "-" + bot.process
global.SYSTEM_EVENT_HANDLER.raiseEvent(key, 'Status Report Updated')
/* We will also reaise the events for the datasets impacted by the process that just finished. */
for (let j = 0; j < bot.processes.length; j++) {
let process = bot.processes[j]
if (process.name === bot.process) {
let updatesDatasets = process.updatesDatasets
if (updatesDatasets !== undefined) {
for (let i = 0; i < updatesDatasets.length; i++) {
let updatedDataSet = updatesDatasets[i]
key = bot.devTeam + "-" + bot.codeName + "-" + updatedDataSet.product + "-" + updatedDataSet.dataSet
let event = {
lastFile: thisObject.file.lastFile
}
global.SYSTEM_EVENT_HANDLER.raiseEvent(key, 'Dataset Updated', event)
}
}
}
}
callBackFunction(global.DEFAULT_OK_RESPONSE);
return;
}
+973
View File
@@ -0,0 +1,973 @@
exports.newTradingBot = function newTradingBot(bot, logger, UTILITIES, FILE_STORAGE) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
const MODULE_NAME = "Trading Bot";
let thisObject = {
initialize: initialize,
finalize: finalize,
start: start
};
let utilities = UTILITIES.newCloudUtilities(logger);
let fileStorage = FILE_STORAGE.newFileStorage(logger);
const COMMONS = require('./Commons.js');
let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE);
let assistant;
return thisObject;
function finalize() {
thisObject = undefined
utilities = undefined
fileStorage = undefined
commons = undefined
}
function initialize(pAssistant, callBackFunction) {
try {
logger.fileName = MODULE_NAME;
logger.initialize();
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
assistant = pAssistant;
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function start(multiPeriodDataFiles, timePeriod, timePeriodLabel, currentDay, interExecutionMemory, callBackFunction) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
let chart = {}
let mainDependency = {}
let processingDailyFiles
if (currentDay !== undefined) {
processingDailyFiles = true
} else {
processingDailyFiles = false
}
/* The first phase here is about checking that we have everything we need at the definition level. */
let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies
if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) {return}
let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets
if (commons.validateOutputDatasets(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. */
for (let j = 0; j < global.marketFilesPeriods.length; j++) {
let timePeriodLabel = marketFilesPeriods[j][1]
let dataFiles = multiPeriodDataFiles.get(timePeriodLabel)
let products = {}
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Inflating Data Files for timePeriod = " + timePeriodLabel); }
if (dataFiles !== undefined) {
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timePeriod)
let propertyName = 'at' + timePeriodLabel.replace('-', '');
chart[propertyName] = products
}
}
for (let j = 0; j < global.dailyFilePeriods.length; j++) {
let timePeriodLabel = global.dailyFilePeriods[j][1]
let dataFiles = multiPeriodDataFiles.get(timePeriodLabel)
let products = {}
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Inflating Data Files for timePeriod = " + timePeriodLabel); }
if (dataFiles !== undefined) {
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timePeriod)
let propertyName = 'at' + timePeriodLabel.replace('-', '');
chart[propertyName] = products
}
}
/* From here we have more or less the same we used to have at JASON */
const TRADING_SIMULATION = require('./TradingSimulation.js');
let tradingSimulation = TRADING_SIMULATION.newTradingSimulation(bot, logger, UTILITIES);
let market = global.MARKET;
const SIMULATED_RECORDS_FOLDER_NAME = "Trading-Simulation";
const CONDITIONS_FOLDER_NAME = "Simulation-Conditions";
const STRATEGIES_FOLDER_NAME = "Simulation-Strategies";
const TRADES_FOLDER_NAME = "Simulation-Trades";
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
let recordsArray
let conditionsArray
let strategiesArray
let tradesArray
let tradingSystem = {};
tradingSimulation.runSimulation(
chart,
dataDependencies,
timePeriod,
timePeriodLabel,
currentDay,
interExecutionMemory,
assistant,
writeFiles,
callBackFunction)
function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray) {
tradingSystem = pTradingSystem
recordsArray = pRecordsArray
conditionsArray = pConditionsArray
strategiesArray = pStrategiesArray
tradesArray = pTradesArray
if (timePeriod > global.dailyFilePeriods[0][0]) {
writeMarketFiles()
} else {
writeDailyFiles()
}
}
function writeMarketFiles() {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> Entering function."); }
writeRecordsFile();
function writeRecordsFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeRecordsFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < recordsArray.length; i++) {
let record = recordsArray[i];
fileContent = fileContent + separator + '[' +
record.begin + "," +
record.end + "," +
record.type + "," +
record.marketRate + "," +
record.amount + "," +
record.balanceA + "," +
record.balanceB + "," +
record.profit + "," +
record.lastTradeProfitLoss + "," +
record.stopLoss + "," +
record.roundtrips + "," +
record.hits + "," +
record.fails + "," +
record.hitRatio + "," +
record.ROI + "," +
record.periods + "," +
record.days + "," +
record.anualizedRateOfReturn + "," +
record.positionRate + "," +
record.lastTradeROI + "," +
record.strategy + "," +
record.strategyStageNumber + "," +
record.takeProfit + "," +
record.stopLossPhase + "," +
record.takeProfitPhase + "," +
JSON.stringify(record.executionRecord) + "," +
record.positionSize + "," +
record.initialBalanceA + "," +
record.minimumBalanceA + "," +
record.maximumBalanceA + "," +
record.initialBalanceB + "," +
record.minimumBalanceB + "," +
record.maximumBalanceB + "," +
record.baseAsset + "," +
record.positionPeriods + "," +
record.positionDays + "," +
record.distanceToLastTriggerOn + "," +
record.distanceToLastTriggerOff + "," +
record.distanceToLastTakePosition + "," +
record.distanceToLastClosePosition + "]";
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriodLabel;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeRecordsFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeRecordsFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeRecordsFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeRecordsFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeRecordsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
writeConditionsFile();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeRecordsFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeRecordsFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeConditionsFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeConditionsFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < conditionsArray.length; i++) {
let record = conditionsArray[i];
let conditions = "";
let conditionsSeparator = "";
for (let j = 0; j < record.length - 3; j++) {
conditions = conditions + conditionsSeparator + record[j];
if (conditionsSeparator === "") { conditionsSeparator = ","; }
}
conditions = conditions + conditionsSeparator + '[' + record[record.length - 3] + ']'; // The last item contains an Array of condition values.
conditions = conditions + conditionsSeparator + '[' + record[record.length - 2] + ']'; // The last item contains an Array of formulaErrors.
conditions = conditions + conditionsSeparator + '[' + record[record.length - 1] + ']'; // The last item contains an Array of formulaValues.
fileContent = fileContent + separator + '[' + conditions + ']';
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
fileContent = "[" + JSON.stringify(tradingSystem) + "," + fileContent + "]";
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + CONDITIONS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriodLabel;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeConditionsFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeConditionsFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeConditionsFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeConditionsFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeConditionsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
writeStrategiesFile();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeConditionsFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeConditionsFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeStrategiesFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeStrategiesFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < strategiesArray.length; i++) {
let record = strategiesArray[i];
fileContent = fileContent + separator + '[' +
record.begin + "," +
record.end + "," +
record.status + "," +
record.number + "," +
record.beginRate + "," +
record.endRate + "]";
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + STRATEGIES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriodLabel;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeStrategiesFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeStrategiesFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeStrategiesFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeStrategiesFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeStrategiesFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
writeTradesFile();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeStrategiesFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeStrategiesFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeTradesFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeTradesFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < tradesArray.length; i++) {
let record = tradesArray[i];
if (record.stopRate === undefined) { record.stopRate = 0 }
fileContent = fileContent + separator + '[' +
record.begin + "," +
record.end + "," +
record.status + "," +
record.lastTradeROI + "," +
record.beginRate + "," +
record.endRate + "," +
record.exitType + "]";
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + TRADES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timePeriodLabel;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeTradesFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeTradesFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeTradesFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeTradesFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeTradesFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
/* Emit event that signals that simulation files were updated */
global.SYSTEM_EVENT_HANDLER.raiseEvent('Jason-Multi-Period', 'Simulation Files Updated')
callBackFunction(global.DEFAULT_OK_RESPONSE);
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeTradesFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeTradesFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
function writeDailyFiles() {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> Entering function."); }
writeRecordsFile();
/* TODO : NEXT function is a work in progress, not used today */
function writeFinalResults() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> Entering function."); }
if ( // We only write this file if we are at the head of the market.
Math.trunc(currentDay.valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS
!==
Math.trunc((new Date()).valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS
) {
writeRecordsFile();
return;
}
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < recordsArray.length; i++) {
let record = recordsArray[i];
/* Will only add to the file the records of the current day */
if (record.begin < currentDay.valueOf()) { continue; }
fileContent = fileContent + separator + '[' +
record.begin + "," +
record.end + "," +
record.type + "," +
record.marketRate + "," +
record.amount + "," +
record.balanceA + "," +
record.balanceB + "," +
record.profit + "," +
record.lastTradeProfitLoss + "," +
record.stopLoss + "," +
record.roundtrips + "," +
record.hits + "," +
record.fails + "," +
record.hitRatio + "," +
record.ROI + "," +
record.periods + "," +
record.days + "," +
record.anualizedRateOfReturn + "," +
record.positionRate + "," +
record.lastTradeROI + "," +
record.strategy + "," +
record.strategyStageNumber + "," +
record.takeProfit + "," +
record.stopLossPhase + "," +
record.takeProfitPhase + "," +
JSON.stringify(record.executionRecord) + "," +
record.positionSize + "," +
record.initialBalanceA + "," +
record.minimumBalanceA + "," +
record.maximumBalanceA + "," +
record.initialBalanceB + "," +
record.minimumBalanceB + "," +
record.maximumBalanceB + "," +
record.baseAsset + "," +
record.positionPeriods + "," +
record.positionDays + "]";
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timePeriodLabel;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
writeRecordsFile();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeRecordsFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeRecordsFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < recordsArray.length; i++) {
let record = recordsArray[i];
/* Will only add to the file the records of the current day */
if (record.begin < currentDay.valueOf()) { continue; }
fileContent = fileContent + separator + '[' +
record.begin + "," +
record.end + "," +
record.type + "," +
record.marketRate + "," +
record.amount + "," +
record.balanceA + "," +
record.balanceB + "," +
record.profit + "," +
record.lastTradeProfitLoss + "," +
record.stopLoss + "," +
record.roundtrips + "," +
record.hits + "," +
record.fails + "," +
record.hitRatio + "," +
record.ROI + "," +
record.periods + "," +
record.days + "," +
record.anualizedRateOfReturn + "," +
record.positionRate + "," +
record.lastTradeROI + "," +
record.strategy + "," +
record.strategyStageNumber + "," +
record.takeProfit + "," +
record.stopLossPhase + "," +
record.takeProfitPhase + "," +
JSON.stringify(record.executionRecord) + "," +
record.positionSize + "," +
record.initialBalanceA + "," +
record.minimumBalanceA + "," +
record.maximumBalanceA + "," +
record.initialBalanceB + "," +
record.minimumBalanceB + "," +
record.maximumBalanceB + "," +
record.baseAsset + "," +
record.positionPeriods + "," +
record.positionDays + "]";
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timePeriodLabel + "/" + dateForPath;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeRecordsFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeRecordsFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeRecordsFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeRecordsFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeRecordsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
writeConditionsFile();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeRecordsFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeRecordsFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeConditionsFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeConditionsFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < conditionsArray.length; i++) {
let record = conditionsArray[i];
/* Will only add to the file the records of the current day */
if (record.begin < currentDay.valueOf()) { continue; }
let conditions = "";
let conditionsSeparator = "";
/* Will only add to the file the records of the current day */
if (record.begin < currentDay.valueOf()) { continue; }
for (let j = 0; j < record.length - 3; j++) {
conditions = conditions + conditionsSeparator + record[j];
if (conditionsSeparator === "") { conditionsSeparator = ","; }
}
conditions = conditions + conditionsSeparator + '[' + record[record.length - 3] + ']'; // The last item contains an Array of condition values.
conditions = conditions + conditionsSeparator + '[' + record[record.length - 2] + ']'; // The last item contains an Array of formulaErrors.
conditions = conditions + conditionsSeparator + '[' + record[record.length - 1] + ']'; // The last item contains an Array of formulaValues.
fileContent = fileContent + separator + '[' + conditions + ']';
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
fileContent = "[" + JSON.stringify(tradingSystem) + "," + fileContent + "]";
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + CONDITIONS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timePeriodLabel + "/" + dateForPath;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeConditionsFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeConditionsFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeConditionsFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeConditionsFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeConditionsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
writeStrategiesFile();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeConditionsFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeConditionsFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeStrategiesFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeStrategiesFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < strategiesArray.length; i++) {
let record = strategiesArray[i];
/* Will only add to the file the records of the current day. In this case since objects can span more than one day, we add all of the objects that ends
at the current date. */
if (record.end < currentDay.valueOf()) { continue; }
fileContent = fileContent + separator + '[' +
record.begin + "," +
record.end + "," +
record.status + "," +
record.number + "," +
record.beginRate + "," +
record.endRate + "]";
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + STRATEGIES_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timePeriodLabel + "/" + dateForPath;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeStrategiesFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeStrategiesFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeStrategiesFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeStrategiesFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeStrategiesFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
writeTradesFile();
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeStrategiesFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeStrategiesFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function writeTradesFile() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeTradesFile -> Entering function."); }
let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
for (let i = 0; i < tradesArray.length; i++) {
let record = tradesArray[i];
/* Will only add to the file the records of the current day. In this case since objects can span more than one day, we add all of the objects that ends
at the current date. */
if (record.end < currentDay.valueOf()) { continue; }
if (record.stopRate === undefined) { record.stopRate = 0 }
fileContent = fileContent + separator + '[' +
record.begin + "," +
record.end + "," +
record.status + "," +
record.lastTradeROI + "," +
record.beginRate + "," +
record.endRate + "," +
record.exitType + "]";
if (separator === "") { separator = ","; }
fileRecordCounter++;
}
fileContent = "[" + fileContent + "]";
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
let fileName = '' + market.assetA + '_' + market.assetB + '.json';
let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion;
let filePath = filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + TRADES_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timePeriodLabel + "/" + dateForPath;
filePath += '/' + fileName
fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated);
function onFileCreated(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeTradesFile -> onFileCreated -> Entering function."); }
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeTradesFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeTradesFile -> onFileCreated -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeTradesFile -> onFileCreated -> filePath = " + filePath);
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeTradesFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB);
callBackFunction(err);
return;
}
/* Emit event that signals that simulation files were updated */
global.SYSTEM_EVENT_HANDLER.raiseEvent('Jason-Multi-Period', 'Simulation Files Updated')
callBackFunction(global.DEFAULT_OK_RESPONSE);
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeTradesFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeTradesFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
};
@@ -1,12 +1,12 @@
exports.newTradingEngineProcessMainLoop = function newTradingEngineProcessMainLoop(bot, parentLogger) {
exports.newTradingBotProcessMainLoop = function newTradingBotProcessMainLoop(bot, parentLogger) {
const ROOT_DIR = './';
const MODULE_NAME = "Trading Engine Process Main Loop";
const MODULE_NAME = "Trading Process Main Loop";
const FULL_LOG = true;
let USER_BOT_MODULE;
let COMMONS_MODULE;
let USER_BOT_COMMONS;
const MULTI_PERIOD_MARKET = require(ROOT_DIR + 'MultiPeriodMarket');
const MULTI_PERIOD_DAILY = require(ROOT_DIR + 'MultiPeriodDaily');
@@ -40,9 +40,20 @@
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
processConfig = pProcessConfig;
if (bot.definedByUI === true) {
/* The code of the bot is defined at the UI. No need to load a file with the code. */
session.initialize(onSessionInitialized)
function onSessionInitialized(err) {
callBackFunction(err);
}
return
}
bot.resumeExecution = processConfig.framework.startDate.resumeExecution // We are inherating this from root, but from here we need it at bot
let filePath = bot.devTeam + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name
let filePath = bot.devTeam + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.codeName
filePath += "/User.Bot.js"
fileStorage.getTextFile(bot.devTeam, filePath, onBotDownloaded);
@@ -52,6 +63,7 @@
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> err = " + err.message);
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> filePath = " + filePath);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
@@ -73,9 +85,9 @@
return;
}
COMMONS_MODULE = {}
//COMMONS_MODULE.newCommons = require(process.env.BOTS_PATH + '/aamasters/AAMasters/bots/AAJason-Trading-Engine-Bot/Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work.
COMMONS_MODULE.newCommons = eval(text); // Use this for production
USER_BOT_COMMONS = {}
//USER_BOT_COMMONS.newCommons = require(process.env.BOTS_PATH + '/aamasters/AAMasters/bots/AAJason-Trading-Engine-Bot/Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work.
USER_BOT_COMMONS.newCommons = eval(text); // Use this for production
session.initialize(onSessionInitialized)
@@ -140,6 +152,8 @@
const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies');
const DATA_DEPENDENCIES = require(ROOT_DIR + 'DataDependencies');
const DATA_SET = require(ROOT_DIR + 'DataSet');
const PROCESS_EXECUTION_EVENTS = require(ROOT_DIR + 'ProcessExecutionEvents');
const PROCESS_OUTPUT = require(ROOT_DIR + 'ProcessOutput');
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
@@ -177,12 +191,162 @@
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
let processOutput
let processExecutionEvents
let userBot;
let processFramework;
let statusDependencies;
let dataDependencies;
initializeStatusDependencies();
initializeProcessExecutionEvents();
function initializeProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> Entering function."); }
processExecutionEvents = PROCESS_EXECUTION_EVENTS.newProcessExecutionEvents(bot, logger)
processExecutionEvents.initialize(undefined, undefined, onInizialized);
function onInizialized(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Execution finished well.");
startProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function startProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> Entering function."); }
processExecutionEvents.start(onStarted);
function onStarted(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Execution finished well.");
initializeStatusDependencies();
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessExecutionEvents -> onStarted -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function initializeStatusDependencies() {
@@ -192,7 +356,7 @@
statusDependencies = STATUS_DEPENDENCIES.newStatusDependencies(bot, logger, STATUS_REPORT, UTILITIES);
statusDependencies.initialize(processConfig.statusDependencies, undefined, undefined, onInizialized);
statusDependencies.initialize(undefined, undefined, onInizialized);
function onInizialized(err) {
@@ -268,7 +432,7 @@
dataDependencies = DATA_DEPENDENCIES.newDataDependencies(bot, logger, DATA_SET);
dataDependencies.initialize(processConfig.dataDependencies, onInizialized);
dataDependencies.initialize(onInizialized);
function onInizialized(err) {
@@ -513,18 +677,8 @@
}
switch (processConfig.framework.name) {
case 'Multi-Period-Market': {
processFramework = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, COMMONS_MODULE, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE);
intitializeProcessFramework();
break;
}
case 'Multi-Period-Daily': {
processFramework = MULTI_PERIOD_DAILY.newMultiPeriodDaily(bot, logger, COMMONS_MODULE, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE);
intitializeProcessFramework();
break;
}
case 'Multi-Period': {
processFramework = MULTI_PERIOD.newMultiPeriod(bot, logger, COMMONS_MODULE, UTILITIES, USER_BOT_MODULE, COMMONS_MODULE);
processFramework = MULTI_PERIOD.newMultiPeriod(bot, logger, UTILITIES, USER_BOT_MODULE, USER_BOT_COMMONS);
intitializeProcessFramework();
break;
}
@@ -848,8 +1002,7 @@
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> saveContext -> onFinished -> Execution finished well."); }
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
raiseEventsProcessOutput()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
@@ -910,6 +1063,155 @@
}
}
function raiseEventsProcessOutput() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> Entering function."); }
processOutput = PROCESS_OUTPUT.newProcessOutput(bot, logger)
processOutput.raiseEvents(statusDependencies, onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> onFinished -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> raiseEventsProcessOutput -> onFinished -> Execution finished well.");
finishProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> raiseEventsProcessOutput -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> onFinished -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> raiseEventsProcessOutput -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function finishProcessExecutionEvents() {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> Entering function."); }
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); }
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Execution finished well.");
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> finishProcessExecutionEvents -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
processStopped()
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Operation Failed. Aborting the process.");
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err = " + err.message);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> err = " + err.stack);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
callBackFunction(err);
}
}
function loopControl(nextWaitTime) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Entering function."); }
+2893
View File
File diff suppressed because it is too large. Load diff
+80 -72
View File
@@ -53,35 +53,37 @@ process.on('exit', function (code) {
console.log('[INFO] Task Server -> server -> process.on.exit -> About to exit -> code = ' + code)
})
/*
/* Here we listen for the message to stop this Task / Process comming from the Task Manager, which is the paret of this node js process. */
process.on('message', message => {
if (message === 'Stop this Task') {
We read the first string sent as an argument when the process was created by the Task Manager. Ther we will find the information of the identity
of this Task and know exactly what to run within this server instance.
global.STOP_TASK_GRACEFULLY = true;
*/
global.TASK_NODE = process.argv[2]
/*
There are some process that might no be able to end grafully, for example the ones schedulle to process information in a future day or month.
In order to be sure that the process will be terminated, we schedulle one forced exit in 2 minutes from now.
*/
console.log('[INFO] Task Server -> server -> process.on -> Executing order received from Task Manager to Stop this Task. Nodejs process will be exited in less than 1 minute.')
setTimeout(global.EXIT_NODE_PROCESS, 60000);
}
});
if (global.TASK_NODE !== undefined) {
global.EXIT_NODE_PROCESS = function exitProcess() {
try {
global.TASK_NODE = JSON.parse(global.TASK_NODE)
console.log('[INFO] Task Server -> server -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE))
} catch (err) {
console.log('[ERROR] Task Server -> server -> global.TASK_NODE -> ' + err.stack)
/* Cleaning Before Exiting. */
clearInterval(global.HEARTBEAT_INTERVAL_HANDLER)
for (let i = 0; i < global.TASK_NODE.bot.processes.length; i++) {
let code = global.TASK_NODE.bot.processes[i].code
let process = global.TASK_NODE.bot.processes[i]
key = process.name + '-' + process.type + '-' + process.id
global.SYSTEM_EVENT_HANDLER.raiseEvent(key, 'Stopped') // Meaning Process Stopped
}
}
else { // I use this section to debug in standalone mode.
let argument = '{"type":"Task","name":"Runs Backtests","bot":{"type":"Trading Engine","code":{"team":"AAMasters","bot":"AAJason","repo":"AAJason-Trading-Engine-Bot"},"processes":[{"type":"Process","subType":"Trading Engine Process","name":"Multi Period","code":{"process":"Multi-Period"},"session":{"type":"Backtesting Session","name":"Backtest 01","code":{"folderName":"Backtest-01"},"parameters":{"type":"Parameters","name":"Parameters","baseAsset":{"type":"Base Asset","name":"Base Asset","code":{"name":"BTC","initialBalance":0.001,"minimumBalance":0.0001,"maximumBalance":1},"id":"666f6f10-2f17-4f5e-951c-b532bdb574d2"},"timeRange":{"type":"Time Range","name":"Time Range","code":{"initialDatetime":"2019-09-24T00:00:00.000Z","finalDatetime":"2019-09-27T00:00:00.000Z"},"id":"172958dd-b268-4444-8163-70979538ea6e"},"timePeriod":{"type":"Time Period","name":"Time Period","code":"10-min","id":"37ee839d-9a7c-410c-9251-c33b8f1b99f7"},"slippage":{"type":"Slippage","name":"Slippage","code":{"positionRate":0.1,"stopLoss":0.1,"takeProfit":0.1},"id":"86ebd973-6ad9-4070-aece-a87623f24c2e"},"feeStructure":{"type":"Fee Structure","name":"Fee Structure","code":{"maker":0.15,"taker":0.25},"id":"a0ec3f6f-6047-4740-87fe-393b1c714adb"},"key":{"type":"Exchange Account Key","name":"New Key","code":"Paste your exchange API secret key here and the put the key name as this key object title. Secret keys are filtered out and NOT exported when using the SHARE menu option on any object at your workspace. Secret keys ARE downloaded when using the download button.","id":"368f879d-e363-47c7-b55e-7b927d896b20"},"id":"09db5e1e-a7e8-468c-ad70-0d2ab1c8b8b8"},"layerManager":{"type":"Layer Manager","name":"New Layer Manager","layers":[{"type":"Layer","name":"Live","code":{"product":"Live-Trading-History"},"id":"0ec05e1c-230b-44a1-9f2c-fba0ea2ff9e2"},{"type":"Layer","name":"Trades","code":{"product":"Simulation-Trades"},"id":"6326e03a-96c0-4d21-b877-f2c6a0419fc5"},{"type":"Layer","name":"Strategies","code":{"product":"Simulation-Strategies"},"id":"bda1e06c-e569-4bd5-95fb-90154aafb003"},{"type":"Layer","name":"Simulation","code":{"product":"Trading-Simulation"},"id":"d58d8cd2-f125-4f0c-b241-08e2af8ac4be"},{"type":"Layer","name":"Formulas & Conditions","code":{"product":"Simulation-Conditions"},"id":"15dfeca0-acd9-40d3-afe0-4805654bf0d0"}],"id":"884c4dd7-4beb-43fb-bda5-d6097d58ae09"},"socialBots":{"type":"Social Bots","name":"New Social Bots","bots":[],"id":"281eb022-cf9f-4ac2-978b-c8358bee8fec"},"id":"121202ea-6735-4bf3-8a95-aaa55f00f6e7"},"id":"3f483482-d8a1-4755-ba50-7cac6296fa5f"}],"id":"25fe9099-b53d-4757-8a63-3f8a15875f33"},"id":"5b21d2d2-0f52-4408-83eb-ddaa844ec58c"}'
/* charly argument = '{"type":"Task","name":"Brings Trades Records from the Exchange","bot":{"type":"Sensor","name":"Charly","processes":[{"type":"Process","name":"Live Trades","code":{"team":"AAMasters","bot":"AACharly","process":"Live-Trades"},"id":"5846ebc7-1979-4a80-9cc7-94bb4b8659dc"},{"type":"Process","name":"Hole Fixing","code":{"team":"AAMasters","bot":"AACharly","process":"Hole-Fixing"},"id":"31fc4f05-75d4-419a-9fb0-73e25e856f15"}]},"id":"5bfef4dc-54c1-44db-ace6-1ab27a86746e"}'
// olivia argument = '{"type":"Task","name":"Generates 1 min to 24 hs Candles & Volumes","bot":{"type":"Indicator","name":"Olivia","processes":[{"type":"Process","name":"Daily","code":{"team":"AAMasters","bot":"AAOlivia","process":"Multi-Period-Daily"},"id":"68cc8e1b-e94a-477e-82d0-15ecc9f1b9e2"},{"type":"Process","name":"Market","code":{"team":"AAMasters","bot":"AAOlivia","process":"Multi-Period-Market"},"id":"e1ac5e3d-d491-4e90-baf4-d4e5b71a8b1a"}]},"id":"efe36e05-75ea-41b5-8d92-c6b27635c834"}'
// bruce argument = ' {"type":"Task","name":"Converts Trades into 1 min Candles & Volumes","bot":{"type":"Indicator","name":"Bruce","processes":[{"type":"Process","name":"New Process","code":{"team":"AAMasters","bot":"AABruce","process":"Single-Period-Daily"},"id":"e184744f-5de0-41c1-ad4c-36960f4ced90"}]},"id":"42758590-a7bd-4712-a5c9-80a3a820c5b3"}'
*/
try {
global.TASK_NODE = JSON.parse(argument)
} catch (err) {
console.log(err.stack)
}
console.log("[INFO] Task Server -> " + global.TASK_NODE.name + " -> EXIT_NODE_PROCESS -> Task Server will stop in 10 seconds.");
setTimeout(process.exit, 10000) // We will give 10 seconds to logs be written on file
}
require('dotenv').config();
@@ -102,54 +104,54 @@ amount of instances started, we can safelly destroy the rest of the objects runn
global.ENDED_PROCESSES_COUNTER = 0
global.TOTAL_PROCESS_INSTANCES_CREATED = 0
/* Here we listen for the message to stop this Task / Process comming from the Task Manager, which is the paret of this node js process. */
process.on('message', message => {
if (message === 'Stop this Task') {
/*
global.STOP_TASK_GRACEFULLY = true;
We read the first string sent as an argument when the process was created by the Task Manager. There we will find the information of the identity
of this Task and know exactly what to run within this server instance.
/*
There are some process that might no be able to end grafully, for example the ones schedulle to process information in a future day or month.
In order to be sure that the process will be terminated, we schedulle one forced exit in 2 minutes from now.
*/
console.log('[INFO] Task Server -> server -> process.on -> Executing order received from Task Manager to Stop this Task. Nodejs process will be exited in less than 1 minute.')
setTimeout(global.EXIT_NODE_PROCESS, 60000);
}
});
global.EXIT_NODE_PROCESS = function exitProcess() {
/* Cleaning Before Exiting. */
clearInterval(global.HEARTBEAT_INTERVAL_HANDLER)
for (let i = 0; i < global.TASK_NODE.bot.processes.length; i++) {
let code = global.TASK_NODE.bot.processes[i].code
/* Delete the event handler for each process. */
let key = global.TASK_NODE.bot.code.team + "-" + global.TASK_NODE.bot.code.bot + "-" + code.process
global.SYSTEM_EVENT_HANDLER.deleteEventHandler(key)
let process = global.TASK_NODE.bot.processes[i]
key = process.name + '-' + process.type + '-' + process.id
global.SYSTEM_EVENT_HANDLER.raiseEvent(key, 'Stopped') // Meaning Process Stopped
}
console.log("[INFO] Task Server -> " + global.TASK_NODE.name + " -> EXIT_NODE_PROCESS -> Task Server will stop in 10 seconds.");
setTimeout(process.exit, 10000) // We will give 10 seconds to logs be written on file
}
*/
let taskId = process.argv[2] // reading what comes as an argument of the nodejs process.
/* Setting up the global Event Handler */
const EVENT_HANDLER_MODULE = require('./SystemEventHandler.js');
const IPC = require('node-ipc');
global.SYSTEM_EVENT_HANDLER = EVENT_HANDLER_MODULE.newSystemEventHandler(IPC)
global.SYSTEM_EVENT_HANDLER.initialize('Task Server', bootLoader)
global.SYSTEM_EVENT_HANDLER.initialize('Task Server', preLoader)
global.STOP_TASK_GRACEFULLY = false;
function preLoader() {
if (taskId !== undefined) {
/* The Task Manager sent the info via a process argument. In this case we listen to an event with the Task Info that should be emitted at the UI */
try {
console.log('[INFO] Task Server -> server -> preLoader -> Listening to starting event -> key = ' + 'Task Server - ' + taskId)
global.SYSTEM_EVENT_HANDLER.listenToEvent('Task Server - ' + taskId, 'Run Task', undefined, undefined, undefined, eventReceived)
function eventReceived(message) {
global.TASK_NODE = message
global.TASK_NODE = JSON.parse(message.event.definition)
bootLoader()
}
} catch (err) {
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE -> ' + err.stack)
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE))
}
}
else { /* This process was started not by the Task Manager, but independently (most likely for debugging purposes). In this case we listen to an event with the Task Info that should be emitted at the UI */
try {
console.log('[INFO] Task Server -> server -> preLoader -> Waiting for event to start debugging...')
global.SYSTEM_EVENT_HANDLER.listenToEvent('Task Server', 'Debug Task Started', undefined, undefined, undefined, startDebugging)
function startDebugging(message) {
global.TASK_NODE = message
global.TASK_NODE = JSON.parse(message.event.definition)
bootLoader()
}
} catch (err) {
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE -> ' + err.stack)
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE))
}
}
}
function bootLoader() {
/* Heartbeat sent to the UI */
@@ -174,28 +176,34 @@ function bootLoader() {
/* Validate that the minimun amount of parameters required are defined. */
if (global.TASK_NODE.bot.code.bot === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Parameter 'bot' at the Indicator | Sensor | Trading Engine is undefined. This process will not be executed. -> Process = " + global.TASK_NODE.bot.processes[processIndex].name);
if (global.TASK_NODE.bot.processes[processIndex].referenceParent === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Process Instance without a Reference Parent. This process will not be executed. -> Process Instance = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex]));
continue
}
if (global.TASK_NODE.bot.code.team === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Parameter 'team' at the bot is undefined. This process will not be executed. -> Process = " + global.TASK_NODE.bot.processes[processIndex].name);
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Process Definition without parent Bot Definition. -> Process Definition = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex].referenceParent));
continue
}
if (global.TASK_NODE.bot.processes[processIndex].code.process === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Parameter 'process' at object Process is undefined. This process will not be executed. -> Process = " + global.TASK_NODE.bot.processes[processIndex].name);
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Bot Definition without parent Team. -> Bot Definition = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode));
continue
}
/* Create the event handler for each process. This event handlers are where the status reports updated events are raised. */
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.code.codeName === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Process Definition without a codeName defined. -> Process Definition = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex].referenceParent));
continue
}
let key = global.TASK_NODE.bot.code.team + "-" + global.TASK_NODE.bot.code.bot + "-" + code.process
global.SYSTEM_EVENT_HANDLER.createEventHandler(key)
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.code.codeName === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Bot Definition without a codeName defined. -> Bot Definition = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode));
continue
}
if (global.TASK_NODE.bot.code.repo === undefined) {
global.TASK_NODE.bot.code.repo = global.TASK_NODE.bot.code.bot + "-" + global.TASK_NODE.bot.type + "-Bot"
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName === undefined) {
console.log("[INFO] Task Server -> server -> bootLoader -> Team without a codeName defined. -> Team Definition = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode));
continue
}
startRoot(processIndex);