diff --git a/IndicatorBotCommons.js b/IndicatorBotCommons.js index 959c6deda..384cf0a2f 100644 --- a/IndicatorBotCommons.js +++ b/IndicatorBotCommons.js @@ -91,17 +91,16 @@ if (property.code.isCalculated === true) { if (property.formula !== undefined) { if (property.formula.code !== undefined) { - let newValue try { - newvalue = eval(property.formula.code) + 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.") } - let currentRecord = product[variableName] - currentRecord[property.code.codeName] = newValue } } } @@ -174,17 +173,16 @@ if (property.code.isCalculated !== true) { if (property.formula !== undefined) { if (property.formula.code !== undefined) { - let newValue try { - newvalue = eval(property.formula.code) + 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.") } - let currentRecord = product[variableName] - currentRecord[property.code.codeName] = newValue } } } diff --git a/IndicatorBotMarket.js b/IndicatorBotMarket.js index 1f6c44456..ec7b1e019 100644 --- a/IndicatorBotMarket.js +++ b/IndicatorBotMarket.js @@ -51,10 +51,11 @@ let products = {} let mainDependency + /* The first phase is about transforming the inputs into a format that can be used to apply the user defined code. */ let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies for (let i = 0; i < dataDependencies.length; i++) { - let dataset = dataDependencies[i].referenceParent + let dataDependencyNode = dataDependencies[i].referenceParent let dataFile = dataFiles[i] let jsonData // Datafile converted into Json objects let inputData // Includes calculated properties @@ -62,39 +63,39 @@ let recordDefinition /* - For each dataset in our data dependencies, we should have da dataFile containing the records needed as an imput for this process. + For each dataDependencyNode in our data dependencies, we should have da dataFile containing the records needed as an imput for this process. What we need to do first is transform those records into JSON objects that can be used by user-defined formulas. The first step does that but with the not calculated properties, the second step adds the calculated properties. */ /* Basic validations to see if we have everything we need. */ - if (dataset.parentNode.code.singularVariableName === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + if (dataDependencyNode.parentNode.code.singularVariableName === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(dataDependencyNode.parentNode)); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } - if (dataset.parentNode.code.pluralVariableName === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Plural Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + if (dataDependencyNode.parentNode.code.pluralVariableName === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Plural Variable Name defined. Product Definition = " + JSON.stringify(dataDependencyNode.parentNode)); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } - if (dataset.parentNode.record === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(dataset.parentNode)); + if (dataDependencyNode.parentNode.record === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(dataDependencyNode.parentNode)); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } - recordDefinition = dataset.parentNode.record - singularVariableName = dataset.parentNode.code.singularVariableName + recordDefinition = dataDependencyNode.parentNode.record + singularVariableName = dataDependencyNode.parentNode.code.singularVariableName /* Transform the raw data into JSON objects */ jsonData = commons.jsonifyDataFile(dataFile, recordDefinition) /* Add the calculated properties */ - if (dataset.parentNode.calculations !== undefined) { - inputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, singularVariableName, timePeriod) + if (dataDependencyNode.parentNode.calculations !== undefined) { + inputData = commons.calculationsProcedure(jsonData, recordDefinition, dataDependencyNode.parentNode.calculations, singularVariableName, timePeriod) } else { inputData = jsonData } - products[dataset.parentNode.code.pluralVariableName] = inputData + products[dataDependencyNode.parentNode.code.pluralVariableName] = inputData /* The main dependency is defined as the first dependency processed. */ if (mainDependency === undefined) { @@ -102,117 +103,135 @@ } } - /* During the next phase, we need to generate the data of the different products this process produces an output */ + /* During the second phase, we need to generate the data of the different products this process produces an output */ let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets for (let i = 0; i < outputDatasets.length; i++) { - let dataset = outputDatasets[i].referenceParent + 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 + 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. /* - For each dataset in our process output, we will build the information based on our input products. + For each outputDatasetNode in our process output, we will build the information based on our input products. */ /* Basic validations to see if we have everything we need. */ - if (dataset.parentNode.code.singularVariableName === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + 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 (dataset.parentNode.code.pluralVariableName === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Plural Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + 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 (dataset.parentNode.record === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(dataset.parentNode)); + 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 (dataset.parentNode.dataBuilding === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Data Building Procedure. Product Definition = " + JSON.stringify(dataset.parentNode)); + 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, "[ERROR] start -> Product Definition without a Data Building Procedure. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode)); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } - recordDefinition = dataset.parentNode.record - singularVariableName = dataset.parentNode.code.singularVariableName + recordDefinition = outputDatasetNode.referenceParent.parentNode.record + singularVariableName = outputDatasetNode.referenceParent.parentNode.code.singularVariableName /* Build the data */ - jsonData = commons.dataBuildingProcedure(products, mainDependency, recordDefinition, dataset.parentNode.dataBuilding, singularVariableName, timePeriod) + jsonData = commons.dataBuildingProcedure(products, mainDependency, recordDefinition, outputDatasetNode.referenceParent.parentNode.dataBuilding, singularVariableName, timePeriod) /* Add the calculated properties */ - if (dataset.parentNode.calculations !== undefined) { - outputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, singularVariableName, timePeriod) + if (outputDatasetNode.referenceParent.parentNode.calculations !== undefined) { + outputData = commons.calculationsProcedure(jsonData, recordDefinition, outputDatasetNode.referenceParent.parentNode.calculations, singularVariableName, timePeriod) } else { outputData = jsonData } - products[dataset.parentNode.code.pluralVariableName] = outputData - } - - - - - - - - - - - - - - let dataFile; - - let bands = []; - let channels = []; - let standardChannels = []; - let subChannels = []; - let standardSubChannels = []; - - dataFile = dataFiles[0]; // We only need the bollinger bands. - - commons.buildBandsArray(dataFile, bands, timePeriod, callBackFunction); - commons.buildChannels(bands, channels, callBackFunction); - commons.buildStandardChannels(bands, standardChannels, callBackFunction); - commons.buildSubChannels(bands, subChannels, callBackFunction); - commons.buildStandardSubChannels(bands, standardSubChannels, callBackFunction); - - let dataDependency = {} - - for (let i = 0; i < processConfig.dataDependencies.length; i++) { - let dependency = processConfig.dataDependencies[i] - let recordDefinition = processConfig.recordDefinition - let dependencyArray = commons.buildDependencyArray(dataFiles[i], recordDefinition); - dependencyArray = commons.addCalculatedProperties(dependencyArray, dependency.singularVariableName, timePeriod); - dataDependency[dependency.pluralVariableName] = dependencyArray - } - - for (let i = 0; i < processConfig.updatesDatasets.length; i++) { - let product = processConfig.updatesDatasets[i].product - let dataset = processConfig.updatesDatasets[i].dataset - let recordDefinition = getRecordDefinition(product) - let records = commons.buildRecords(dataDependency, recordDefinition) - let fileContent = generateFileContent(indicatorData, recordDefinition) - writeFile(product, dataset, fileContent) + products[outputDatasetNode.referenceParent.parentNode.code.pluralVariableName] = outputData } + /*At the third 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 contextSummary = {} + + /* Some very basic validations that we have all the information needed. */ + 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 + } + + /* 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 = generateFileContent(outputData, outputDatasetNode.referenceParent.parentNode.record) + writeFile(contextSummary, fileContent) + } + function anotherFileWritten() { totalFilesWritten++ if (totalFilesWritten === processConfig.updatesDatasets.length) { callBackFunction(global.DEFAULT_OK_RESPONSE); - } - } - - function getRecordDefinition(product) { - for (let j = 0; j < bot.products.length; j++) { - if (bot.products[j].codeName === product) { - return bot.products[j].recordDefinition - } } } @@ -229,17 +248,19 @@ let record = records[i]; fileContent = fileContent + recordSeparator + '[' let propertySeparator = "" - for (let j = 0; j < recordDefinition.length; j++) { - let property = recordDefinition[j] - fileContent = fileContent + propertySeparator - if (property.isNumeric !== true) { - fileContent = fileContent + '"' + 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.isNumeric !== true) { + fileContent = fileContent + '"' + } + fileContent = fileContent + record[property.code.codeName] + if (property.code.isNumeric !== true) { + fileContent = fileContent + '"' + } + if (propertySeparator === "") { propertySeparator = ","; } } - fileContent = fileContent + record[property.name] - if (property.isNumeric !== true) { - fileContent = fileContent + '"' - } - if (recordSeparator === "") { propertySeparator = ","; } } fileContent = fileContent + ']' if (recordSeparator === "") { recordSeparator = ","; } @@ -253,7 +274,7 @@ } } - function writeFile(product, dataset, fileContent) { + function writeFile(contextSummary, fileContent) { try { @@ -261,11 +282,11 @@ let fileName = '' + market.assetA + '_' + market.assetB + '.json'; - let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; - let filePath = filePathRoot + "/Output/" + product + "/" + dataset + "/" + outputPeriodLabel; + 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 + "/" + outputPeriodLabel; filePath += '/' + fileName - fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + fileStorage.createTextFile(contextSummary.devTeam, filePath, fileContent + '\n', onFileCreated); function onFileCreated(err) {