Build Data Function Implemented
This commit is contained in:
1 parent
8eaff70835
commit
5e91af82d4
3 files changed
+217
-479
No files matched your search
+102
-428
@@ -10,10 +10,7 @@
|
||||
let thisObject = {
|
||||
jsonifyDataFile: jsonifyDataFile,
|
||||
calculationsProcedure: calculationsProcedure,
|
||||
buildStandardChannels: buildStandardChannels,
|
||||
buildSubChannels: buildSubChannels,
|
||||
buildStandardSubChannels: buildStandardSubChannels,
|
||||
buildRecords: buildRecords
|
||||
dataBuildingProcedure: dataBuildingProcedure
|
||||
};
|
||||
|
||||
return thisObject;
|
||||
@@ -54,26 +51,39 @@
|
||||
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 amond different code blocks and formulas.
|
||||
let resultingArray = []
|
||||
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) {
|
||||
eval(calculationsProcedure.initialization.code.code)
|
||||
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 i = 0; i < jsonArray.length; i++) {
|
||||
for (let index = 0; index < jsonArray.length; index++) {
|
||||
|
||||
let indicator = {}
|
||||
indicator[variableName] = jsonArray[i]
|
||||
let product = {}
|
||||
product[variableName] = jsonArray[index]
|
||||
|
||||
/* This is Loop Code */
|
||||
eval(calculationsProcedure.loop.code.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++) {
|
||||
@@ -81,8 +91,16 @@
|
||||
if (property.code.isCalculated === true) {
|
||||
if (property.formula !== undefined) {
|
||||
if (property.formula.code !== undefined) {
|
||||
let newValue = eval(property.formula.code)
|
||||
let currentRecord = indicator[variableName]
|
||||
let newValue
|
||||
try {
|
||||
newvalue = eval(property.formula.code)
|
||||
} 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
|
||||
}
|
||||
}
|
||||
@@ -90,440 +108,96 @@
|
||||
}
|
||||
|
||||
/* Adding the new element to the resulting array */
|
||||
resultingArray.push(indicator.bollingerBand);
|
||||
results.push(product[variableName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultingArray
|
||||
return results
|
||||
}
|
||||
|
||||
function addCalculatedProperties(dependencyArray, variableName, timePeriod) {
|
||||
function dataBuildingProcedure(products, mainDependency, recordDefinition, dataBuildingProcedure, variableName, timePeriod) {
|
||||
|
||||
let dependecyArray = []
|
||||
/*
|
||||
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 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 */
|
||||
let lastMovingAverage = 0;
|
||||
const SIDE_TOLERANCE = 0.5 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
const SMALL_SLOPE = 1.0 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
const MEDIUM_SLOPE = 2.0 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
const HIGH_SLOPE = 4.0 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is Initialization Code */
|
||||
if (dataBuildingProcedure.loop !== undefined) {
|
||||
if (dataBuildingProcedure.loop.code !== undefined) {
|
||||
for (let index = 0; index < mainDependency.length; index++) {
|
||||
|
||||
for (let i = 0; i < dataFile.length; i++) {
|
||||
let record = {
|
||||
previous: mainDependency[index-1],
|
||||
current: mainDependency[index],
|
||||
next: mainDependency[index+1]
|
||||
}
|
||||
|
||||
let indicator = {}
|
||||
indicator[variableName] = dataFile[i]
|
||||
let product = {}
|
||||
product[variableName] = {}
|
||||
|
||||
/* This is Add Properties Code */
|
||||
if (lastMovingAverage > indicator.bollingerBand.movingAverage) { indicator.bollingerBand.direction = 'Down'; }
|
||||
if (lastMovingAverage < indicator.bollingerBand.movingAverage) { indicator.bollingerBand.direction = 'Up'; }
|
||||
if (lastMovingAverage === indicator.bollingerBand.movingAverage) { indicator.bollingerBand.direction = 'Side'; }
|
||||
/* 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.")
|
||||
}
|
||||
|
||||
let delta = Math.abs(indicator.bollingerBand.movingAverage - lastMovingAverage);
|
||||
|
||||
indicator.bollingerBand.slope = 'Extreme';
|
||||
if (delta < indicator.bollingerBand.movingAverage * HIGH_SLOPE / 100) { indicator.bollingerBand.slope = 'Steep'; }
|
||||
if (delta < indicator.bollingerBand.movingAverage * MEDIUM_SLOPE / 100) { indicator.bollingerBand.slope = 'Medium'; }
|
||||
if (delta < indicator.bollingerBand.movingAverage * SMALL_SLOPE / 100) { indicator.bollingerBand.slope = 'Gentle'; }
|
||||
if (delta < indicator.bollingerBand.movingAverage * SIDE_TOLERANCE / 100) { indicator.bollingerBand.slope = 'Side'; }
|
||||
|
||||
lastMovingAverage = indicator.bollingerBand.movingAverage;
|
||||
/* This is Add Properties Code */
|
||||
|
||||
dependecyArray.push(indicator.bollingerBand);
|
||||
}
|
||||
|
||||
return dependecyArray
|
||||
}
|
||||
|
||||
function buildRecords(dataDependency, recordDefinition) {
|
||||
let records = []
|
||||
|
||||
/* Initialization Code */
|
||||
let period = 1
|
||||
/* Initialization Code */
|
||||
|
||||
for (let i = 0; i < dataDependency.bollinerBands.length; i++) {
|
||||
|
||||
/* Calculations Code*/
|
||||
if (i === 0) {continue}
|
||||
let currentBand = dataDependency.bollinerBands[i];
|
||||
let previousBand = dataDependency.bollinerBands[i - 1];
|
||||
|
||||
if (currentBand.direction === previousBand.direction) {
|
||||
period++
|
||||
} else {
|
||||
period = 1
|
||||
}
|
||||
/* Calculations Code*/
|
||||
|
||||
let record = {
|
||||
begin: currentBand.begin, /* Property Formula Code */
|
||||
end: currentBand.end, /* Property Formula Code */
|
||||
direction: currentBand.direction, /* Property Formula Code */
|
||||
period: period /* Property Formula Code */
|
||||
};
|
||||
records.push(record)
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
|
||||
function buildBandsArray(dataFile, bands, timePeriod, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
let lastMovingAverage = 0;
|
||||
const SIDE_TOLERANCE = 0.5 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
const SMALL_SLOPE = 1.0 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
const MEDIUM_SLOPE = 2.0 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
const HIGH_SLOPE = 4.0 * timePeriod / ONE_DAY_IN_MILISECONDS;
|
||||
|
||||
for (let i = 0; i < dataFile.length; i++) {
|
||||
|
||||
let band = {
|
||||
begin: undefined,
|
||||
end: undefined,
|
||||
movingAverage: 10000000000000,
|
||||
standardDeviation: 0,
|
||||
deviation: undefined
|
||||
};
|
||||
|
||||
band.begin = dataFile[i][0];
|
||||
band.end = dataFile[i][1];
|
||||
|
||||
band.movingAverage = dataFile[i][2];
|
||||
band.standardDeviation = dataFile[i][3];
|
||||
band.deviation = dataFile[i][4];
|
||||
|
||||
if (lastMovingAverage > band.movingAverage) { band.direction = 'Down'; }
|
||||
if (lastMovingAverage < band.movingAverage) { band.direction = 'Up'; }
|
||||
if (lastMovingAverage === band.movingAverage) { band.direction = 'Side'; }
|
||||
|
||||
let delta = Math.abs(band.movingAverage - lastMovingAverage);
|
||||
|
||||
band.slope = 'Extreme';
|
||||
if (delta < band.movingAverage * HIGH_SLOPE / 100) { band.slope = 'Steep'; }
|
||||
if (delta < band.movingAverage * MEDIUM_SLOPE / 100) { band.slope = 'Medium'; }
|
||||
if (delta < band.movingAverage * SMALL_SLOPE / 100) { band.slope = 'Gentle'; }
|
||||
if (delta < band.movingAverage * SIDE_TOLERANCE / 100) { band.slope = 'Side'; }
|
||||
|
||||
bands.push(band);
|
||||
|
||||
lastMovingAverage = band.movingAverage;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function buildChannels(bands, channels, callBackFunction) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildChannels -> Entering function."); }
|
||||
|
||||
try {
|
||||
|
||||
let channel;
|
||||
|
||||
for (let i = 0; i < bands.length; i++) {
|
||||
|
||||
let currentBand = bands[i];
|
||||
let nextBand;
|
||||
|
||||
if (i < bands.length - 1) {
|
||||
nextBand = bands[i + 1];
|
||||
|
||||
if (
|
||||
currentBand.direction === nextBand.direction) {
|
||||
|
||||
if (channel === undefined) {
|
||||
|
||||
channel = {
|
||||
begin: undefined,
|
||||
end: undefined,
|
||||
direction: undefined,
|
||||
period: 0,
|
||||
firstMovingAverage: 0,
|
||||
lastMovingAverage: 0,
|
||||
firstDeviation: 0,
|
||||
lastDeviation: 0
|
||||
};
|
||||
|
||||
channel.direction = currentBand.direction;
|
||||
channel.period = 2;
|
||||
|
||||
channel.begin = currentBand.begin;
|
||||
channel.end = nextBand.end;
|
||||
|
||||
channel.firstMovingAverage = currentBand.movingAverage;
|
||||
channel.lastMovingAverage = nextBand.movingAverage;
|
||||
|
||||
channel.firstDeviation = currentBand.deviation;
|
||||
channel.lastDeviation = nextBand.deviation;
|
||||
|
||||
} else {
|
||||
|
||||
channel.period++;
|
||||
channel.end = nextBand.end;
|
||||
channel.lastMovingAverage = nextBand.movingAverage;
|
||||
channel.lastDeviation = nextBand.deviation;
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
if (channel !== undefined) {
|
||||
channels.push(channel);
|
||||
channel = undefined;
|
||||
} else {
|
||||
/* The channel has only one period */
|
||||
|
||||
channel = {};
|
||||
|
||||
channel.direction = currentBand.direction;
|
||||
channel.period = 1;
|
||||
|
||||
channel.begin = currentBand.begin;
|
||||
channel.end = currentBand.end;
|
||||
|
||||
channel.firstMovingAverage = currentBand.movingAverage;
|
||||
channel.lastMovingAverage = currentBand.movingAverage;
|
||||
|
||||
channel.firstDeviation = currentBand.deviation;
|
||||
channel.lastDeviation = currentBand.deviation;
|
||||
|
||||
channels.push(channel);
|
||||
channel = undefined;
|
||||
/* 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) {
|
||||
let newValue
|
||||
try {
|
||||
newvalue = eval(property.formula.code)
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (channel !== undefined) {
|
||||
channel.period++;
|
||||
channel.end = currentBand.end;
|
||||
channel.lastMovingAverage = currentBand.movingAverage;
|
||||
channel.lastDeviation = currentBand.deviation;
|
||||
channels.push(channel);
|
||||
channel = undefined;
|
||||
} else {
|
||||
/* The channel has only one period */
|
||||
|
||||
channel = {};
|
||||
|
||||
channel.direction = currentBand.direction;
|
||||
channel.period = 1;
|
||||
|
||||
channel.begin = currentBand.begin;
|
||||
channel.end = currentBand.end;
|
||||
|
||||
channel.firstMovingAverage = currentBand.movingAverage;
|
||||
channel.lastMovingAverage = currentBand.movingAverage;
|
||||
|
||||
channel.firstDeviation = currentBand.deviation;
|
||||
channel.lastDeviation = currentBand.deviation;
|
||||
|
||||
channels.push(channel);
|
||||
channel = undefined;
|
||||
/* If within the code the new data structure was not yet pushed to the results array, we do it */
|
||||
if (dataBuildingProcedure.loop.code.code.indexOf('results.push') < 0) {
|
||||
/* Adding the new element to the resulting array */
|
||||
results.push(product[variableName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] buildChannels -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function buildStandardChannels(bands, standardChannels, callBackFunction) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildStandardChannels -> Entering function."); }
|
||||
|
||||
try {
|
||||
|
||||
let period = 1
|
||||
|
||||
for (let i = 1; i < bands.length; i++) {
|
||||
|
||||
let channel;
|
||||
let currentBand = bands[i];
|
||||
let previousBand = bands[i - 1];
|
||||
|
||||
if (currentBand.direction === previousBand.direction) {
|
||||
period++
|
||||
} else {
|
||||
period = 1
|
||||
}
|
||||
|
||||
channel = {
|
||||
begin: currentBand.begin,
|
||||
end: currentBand.end,
|
||||
direction: currentBand.direction,
|
||||
period: period
|
||||
};
|
||||
|
||||
standardChannels.push(channel)
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] buildStandardChannels -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function buildSubChannels(bands, subChannels, callBackFunction) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildSubChannels -> Entering function."); }
|
||||
|
||||
try {
|
||||
|
||||
let channel;
|
||||
|
||||
for (let i = 0; i < bands.length; i++) {
|
||||
|
||||
let currentBand = bands[i];
|
||||
let nextBand;
|
||||
|
||||
if (i < bands.length - 1) {
|
||||
nextBand = bands[i + 1];
|
||||
|
||||
if (
|
||||
currentBand.direction === nextBand.direction &&
|
||||
currentBand.slope === nextBand.slope) {
|
||||
|
||||
if (channel === undefined) {
|
||||
|
||||
channel = {
|
||||
begin: undefined,
|
||||
end: undefined,
|
||||
direction: undefined,
|
||||
slope: undefined,
|
||||
period: 0,
|
||||
firstMovingAverage: 0,
|
||||
lastMovingAverage: 0,
|
||||
firstDeviation: 0,
|
||||
lastDeviation: 0
|
||||
};
|
||||
|
||||
channel.direction = currentBand.direction;
|
||||
channel.slope = currentBand.slope;
|
||||
channel.period = 2;
|
||||
|
||||
channel.begin = currentBand.begin;
|
||||
channel.end = nextBand.end;
|
||||
|
||||
channel.firstMovingAverage = currentBand.movingAverage;
|
||||
channel.lastMovingAverage = nextBand.movingAverage;
|
||||
|
||||
channel.firstDeviation = currentBand.deviation;
|
||||
channel.lastDeviation = nextBand.deviation;
|
||||
|
||||
} else {
|
||||
|
||||
channel.period++;
|
||||
channel.end = nextBand.end;
|
||||
channel.lastMovingAverage = nextBand.movingAverage;
|
||||
channel.lastDeviation = nextBand.deviation;
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
if (channel !== undefined) {
|
||||
subChannels.push(channel);
|
||||
channel = undefined;
|
||||
} else {
|
||||
/* The channel has only one period */
|
||||
|
||||
channel = {};
|
||||
|
||||
channel.direction = currentBand.direction;
|
||||
channel.slope = currentBand.slope;
|
||||
channel.period = 1;
|
||||
|
||||
channel.begin = currentBand.begin;
|
||||
channel.end = currentBand.end;
|
||||
|
||||
channel.firstMovingAverage = currentBand.movingAverage;
|
||||
channel.lastMovingAverage = currentBand.movingAverage;
|
||||
|
||||
channel.firstDeviation = currentBand.deviation;
|
||||
channel.lastDeviation = currentBand.deviation;
|
||||
|
||||
subChannels.push(channel);
|
||||
channel = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (channel !== undefined) {
|
||||
channel.period++;
|
||||
channel.end = currentBand.end;
|
||||
channel.lastMovingAverage = currentBand.movingAverage;
|
||||
channel.lastDeviation = currentBand.deviation;
|
||||
subChannels.push(channel);
|
||||
channel = undefined;
|
||||
} else {
|
||||
/* The channel has only one period */
|
||||
|
||||
channel = {};
|
||||
|
||||
channel.direction = currentBand.direction;
|
||||
channel.slope = currentBand.slope;
|
||||
channel.period = 1;
|
||||
|
||||
channel.begin = currentBand.begin;
|
||||
channel.end = currentBand.end;
|
||||
|
||||
channel.firstMovingAverage = currentBand.movingAverage;
|
||||
channel.lastMovingAverage = currentBand.movingAverage;
|
||||
|
||||
channel.firstDeviation = currentBand.deviation;
|
||||
channel.lastDeviation = currentBand.deviation;
|
||||
|
||||
subChannels.push(channel);
|
||||
channel = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] buildSubChannels -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function buildStandardSubChannels(bands, standardSubChannels, callBackFunction) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildStandardSubChannels -> Entering function."); }
|
||||
|
||||
try {
|
||||
|
||||
let period = 1
|
||||
|
||||
for (let i = 1; i < bands.length; i++) {
|
||||
|
||||
let channel;
|
||||
let currentBand = bands[i];
|
||||
let previousBand = bands[i - 1];
|
||||
|
||||
if (currentBand.direction === previousBand.direction && currentBand.slope === previousBand.slope) {
|
||||
period++
|
||||
} else {
|
||||
period = 1
|
||||
}
|
||||
|
||||
channel = {
|
||||
begin: currentBand.begin,
|
||||
end: currentBand.end,
|
||||
direction: currentBand.direction,
|
||||
slope: currentBand.slope,
|
||||
period: period
|
||||
};
|
||||
|
||||
standardSubChannels.push(channel)
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] buildStandardSubChannels -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
return results
|
||||
}
|
||||
};
|
||||
+67
-10
@@ -48,6 +48,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
|
||||
|
||||
let market = global.MARKET;
|
||||
let products = {}
|
||||
let mainDependency
|
||||
|
||||
let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies
|
||||
for (let i = 0; i < dataDependencies.length; i++) {
|
||||
@@ -56,7 +58,7 @@
|
||||
let dataFile = dataFiles[i]
|
||||
let jsonData // Datafile converted into Json objects
|
||||
let inputData // Includes calculated properties
|
||||
let variableName // name of the variable for this product
|
||||
let singularVariableName // name of the variable for this product
|
||||
let recordDefinition
|
||||
|
||||
/*
|
||||
@@ -66,8 +68,13 @@
|
||||
*/
|
||||
|
||||
/* Basic validations to see if we have everything we need. */
|
||||
if (dataset.parentNode.code.variableName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode));
|
||||
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));
|
||||
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));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
@@ -76,8 +83,52 @@
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
if (dataset.parentNode.calculations === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Calculations Procedure. Product Definition = " + JSON.stringify(dataset.parentNode));
|
||||
|
||||
recordDefinition = dataset.parentNode.record
|
||||
singularVariableName = dataset.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)
|
||||
} else {
|
||||
inputData = jsonData
|
||||
}
|
||||
products[dataset.parentNode.code.pluralVariableName] = inputData
|
||||
|
||||
/* The main dependency is defined as the first dependency processed. */
|
||||
if (mainDependency === undefined) {
|
||||
mainDependency = inputData
|
||||
}
|
||||
}
|
||||
|
||||
/* During the next 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 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
|
||||
|
||||
/*
|
||||
For each dataset 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));
|
||||
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));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
if (dataset.parentNode.record === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(dataset.parentNode));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
@@ -88,16 +139,22 @@
|
||||
}
|
||||
|
||||
recordDefinition = dataset.parentNode.record
|
||||
variableName = dataset.parentNode.code.variableName
|
||||
/* Transform the raw data into JSON objects */
|
||||
jsonData = commons.jsonifyDataFile(dataFile, recordDefinition)
|
||||
singularVariableName = dataset.parentNode.code.singularVariableName
|
||||
|
||||
/* Build the data */
|
||||
jsonData = commons.dataBuildingProcedure(products, mainDependency, recordDefinition, dataset.parentNode.dataBuilding, singularVariableName, timePeriod)
|
||||
|
||||
/* Add the calculated properties */
|
||||
if (dataset.parentNode.calculations !== undefined) {
|
||||
inputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, variableName, timePeriod)
|
||||
outputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, singularVariableName, timePeriod)
|
||||
} else {
|
||||
outputData = jsonData
|
||||
}
|
||||
products[dataset.parentNode.code.pluralVariableName] = outputData
|
||||
}
|
||||
|
||||
/* During the next phase, we need to generate the data of the different products this process produces an output */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -53,46 +53,6 @@ process.on('exit', function (code) {
|
||||
console.log('[INFO] Task Server -> server -> process.on.exit -> About to exit -> code = ' + code)
|
||||
})
|
||||
|
||||
/*
|
||||
|
||||
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.TASK_NODE = process.argv[2]
|
||||
|
||||
if (global.TASK_NODE !== undefined) {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
else { // I use this section to debug in standalone mode.
|
||||
global.TASK_NODE = { "type": "Task", "name": "Generates Bollinger Channels & Sub-Channels", "bot": { "type": "Indicator Bot Instance", "name": "Paula", "code": { "team": "AAMasters", "bot": "AAPaula", "repo": "AAPaula-Indicator-Bot" }, "processes": [{ "type": "Process Instance", "subType": "Indicator Process Instance", "name": "Market", "code": { "process": "Multi-Period-Market" }, "id": "6ddd81e2-d6db-4814-9c6c-96538a74824c", "referenceParent": { "type": "Process Definition", "name": "Multi-Period-Market", "code": { "codeName": "Multi-Period-Market", "description": "Produces for each market two files with bollinger channels respectively.", "startMode": { "allMonths": { "run": "false", "minYear": "", "maxYear": "" }, "oneMonth": { "run": "false", "year": "", "month": "" }, "noTime": { "run": "true" }, "fixedInterval": { "run": "false", "interval": 0 } }, "deadWaitTime": 0, "normalWaitTime": 0, "retryWaitTime": 10000, "sleepWaitTime": 3600000, "comaWaitTime": 86400000, "framework": { "name": "Multi-Period-Market", "startDate": {}, "endDate": {} } }, "id": "28be432d-80ca-46b3-859a-55541e24b2b4", "processOutput": { "type": "Process Output", "name": "New Process Output", "outputDatasets": [{ "type": "Output Dataset", "name": "Bollinger Channels", "id": "d804e799-7c12-42f5-8de2-52a3a7d5daa4", "referenceParent": { "type": "Dataset Definition", "name": "Market", "code": { "codeName": "Multi-Period-Market", "type": "Market Files", "validPeriods": ["24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs"], "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Channels/Multi-Period-Market/@Period", "fileName": "@AssetA_@AssetB.json" }, "parentNode": { "type": "Product Definition", "name": "Bollinger Channels", "code": { "codeName": "Bollinger-Channels", "displayName": "Bollinger-Channels", "description": "Two sets of files per period that contains Bollinger-Bands-Channels-Patterns.", "shareWith": "Public" }, "datasets": [], "record": { "type": "Record Definition", "name": "New Record Definition", "properties": [{ "type": "Record Property", "name": "Begin", "code": { "codeName": "begin", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "caf8122c-3a07-4263-a56f-ffb05df281d6" }, "id": "06edb099-ff64-4528-b8c6-599154bc2ddf" }, { "type": "Record Property", "name": "End", "code": { "codeName": "end", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "c8ec0868-8413-468c-88d5-3e43169395e0" }, "id": "94656d1f-508a-4e94-a8d2-013690aac596" }, { "type": "Record Property", "name": "Direction", "code": { "codeName": "direction", "isNumeric": false }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "e913afe9-b610-4777-bc9e-6349d436a90a" }, "id": "edc0f697-f5e2-446f-bae8-8db7adf91d23" }, { "type": "Record Property", "name": "Period", "code": { "codeName": "period", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "83fce657-a0bb-41ee-80d1-9e2ab980c472" }, "id": "eb733f85-6cf5-485e-9bd3-2bf78733c492" }, { "type": "Record Property", "name": "First Moving Average", "code": { "codeName": "firstMovingAverage", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "52490460-35e3-469a-824f-5b139571d4a0" }, "id": "a67a15ee-6f7f-48bd-9d55-82c57efc993b" }, { "type": "Record Property", "name": "Last Moving Average", "code": { "codeName": "lastMovingAverage", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "41edc1ef-293a-4ceb-bf67-8042e8fdc4eb" }, "id": "0f05bffe-d668-4d25-ab67-d55a4a7c8f5d" }, { "type": "Record Property", "name": "First Deviation", "code": { "codeName": "firstDeviation", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "5af02103-9bc9-4e6c-9684-5a612adfa495" }, "id": "eae84509-b689-4a76-9277-eed72af491dd" }, { "type": "Record Property", "name": "Last Deviation", "code": { "codeName": "lastDeviation", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "bc82d292-e71a-4367-9b07-a0e3982ad60d" }, "id": "d5c32d1f-9e3c-48e8-8025-a17d57c0812e" }], "id": "6c3e68b0-b781-4c53-9ff7-67c3f747ac8a" }, "parentNode": { "type": "Indicator Bot", "name": "Paula", "code": { "codeName": "AAPaula" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "bd0f325d-6f98-468b-8b7b-99a42a175d80" }, "id": "1f111f72-624f-4166-9f99-ab8d785d5267" }, "id": "610cd062-ab88-4892-b711-0fb430305c61" } }, { "type": "Output Dataset", "name": "Bollinger Standard Channels", "id": "e524685d-8da0-41f6-839d-9a4100e6e3fe", "referenceParent": { "type": "Dataset Definition", "name": "Line truncated
|
||||
}
|
||||
|
||||
require('dotenv').config();
|
||||
|
||||
global.WRITE_LOGS_TO_FILES = process.env.WRITE_LOGS_TO_FILES
|
||||
|
||||
/* Default parameters can be changed by the execution configuration */
|
||||
global.EXCHANGE_NAME = 'Poloniex'
|
||||
global.MARKET = { assetA: 'USDT', assetB: 'BTC' }
|
||||
global.CLONE_EXECUTOR = { codeName: 'AACloud', version: '1.1' } // NOTE: To refactor the name of this variable you would need to go through the bots code that are using it.
|
||||
|
||||
/*
|
||||
We need to count how many process instances we deployd and how many of them have already finished their job, either
|
||||
because they just finished or because there was a request to stop the proceses. In this way, once we reach the
|
||||
amount of instances started, we can safelly destroy the rest of the objects running and let this nodejs process die.
|
||||
*/
|
||||
|
||||
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') {
|
||||
@@ -133,14 +93,61 @@ global.EXIT_NODE_PROCESS = function exitProcess() {
|
||||
setTimeout(process.exit, 10000) // We will give 10 seconds to logs be written on file
|
||||
}
|
||||
|
||||
require('dotenv').config();
|
||||
|
||||
global.WRITE_LOGS_TO_FILES = process.env.WRITE_LOGS_TO_FILES
|
||||
|
||||
/* Default parameters can be changed by the execution configuration */
|
||||
global.EXCHANGE_NAME = 'Poloniex'
|
||||
global.MARKET = { assetA: 'USDT', assetB: 'BTC' }
|
||||
global.CLONE_EXECUTOR = { codeName: 'AACloud', version: '1.1' } // NOTE: To refactor the name of this variable you would need to go through the bots code that are using it.
|
||||
|
||||
/*
|
||||
We need to count how many process instances we deployd and how many of them have already finished their job, either
|
||||
because they just finished or because there was a request to stop the proceses. In this way, once we reach the
|
||||
amount of instances started, we can safelly destroy the rest of the objects running and let this nodejs process die.
|
||||
*/
|
||||
|
||||
global.ENDED_PROCESSES_COUNTER = 0
|
||||
global.TOTAL_PROCESS_INSTANCES_CREATED = 0
|
||||
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
global.TASK_NODE = process.argv[2]
|
||||
|
||||
/* 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 (global.TASK_NODE !== undefined) {
|
||||
/* The Task Manager sent the info via a process argument. */
|
||||
try {
|
||||
global.TASK_NODE = JSON.parse(global.TASK_NODE)
|
||||
console.log('[INFO] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE))
|
||||
} catch (err) {
|
||||
console.log('[ERROR] Task Server -> server -> preLoader -> vglobal.TASK_NODE -> ' + err.stack)
|
||||
}
|
||||
bootLoader()
|
||||
}
|
||||
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 */
|
||||
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 = JSON.parse(message.event.definition)
|
||||
bootLoader()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bootLoader() {
|
||||
|
||||
/* Heartbeat sent to the UI */
|
||||
|
||||
Reference in new issue
Block a user