22 files changed
+4018
-6354
No files matched your search
-1127
File diff suppressed because it is too large.
Load diff
+37
-30
@@ -3,6 +3,7 @@
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
|
||||
const ONE_MIN_IN_MILISECONDS = 60 * 1000;
|
||||
|
||||
const MODULE_NAME = "Commons";
|
||||
|
||||
@@ -11,7 +12,7 @@
|
||||
validateOutputDatasets: validateOutputDatasets,
|
||||
inflateDatafiles: inflateDatafiles,
|
||||
dataBuildingProcedure: dataBuildingProcedure,
|
||||
calculationsProcedure: calculationsProcedure,
|
||||
calculationsProcedure: calculationsProcedure,
|
||||
generateFileContent: generateFileContent,
|
||||
writeFile: writeFile
|
||||
};
|
||||
@@ -24,15 +25,15 @@
|
||||
function validateDataDependencies(dataDependencies, callBackFunction) {
|
||||
for (let i = 0; i < dataDependencies.length; i++) {
|
||||
|
||||
let dataDependencyNode = dataDependencies[i]
|
||||
let dataDependencyNode = dataDependencies[i]
|
||||
|
||||
/* Basic validations to see if we have everything we need. */
|
||||
if (dataDependencyNode.referenceParent.parentNode.code.singularVariableName === undefined) {
|
||||
if (dataDependencyNode.referenceParent.parentNode.config.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) {
|
||||
if (dataDependencyNode.referenceParent.parentNode.config.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
|
||||
@@ -55,12 +56,17 @@
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
if (outputDatasetNode.referenceParent.parentNode.code.singularVariableName === undefined) {
|
||||
if (outputDatasetNode.referenceParent.parentNode === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Dataset not a child of a Product Definition. Dataset = " + JSON.stringify(outputDatasetNode.referenceParent));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
if (outputDatasetNode.referenceParent.parentNode.config.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) {
|
||||
if (outputDatasetNode.referenceParent.parentNode.config.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
|
||||
@@ -73,7 +79,7 @@
|
||||
if (outputDatasetNode.referenceParent.parentNode.dataBuilding === undefined) {
|
||||
logger.write(MODULE_NAME, "[WARN] start -> Product Definition " + outputDatasetNode.referenceParent.parentNode.name + " without a Data Building Procedure. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
|
||||
}
|
||||
if (outputDatasetNode.referenceParent.code.codeName === undefined) {
|
||||
if (outputDatasetNode.referenceParent.config.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
|
||||
@@ -85,7 +91,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
if (outputDatasetNode.referenceParent.parentNode.code.codeName === undefined) {
|
||||
if (outputDatasetNode.referenceParent.parentNode.config.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
|
||||
@@ -97,7 +103,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
if (outputDatasetNode.referenceParent.parentNode.parentNode.code.codeName === undefined) {
|
||||
if (outputDatasetNode.referenceParent.parentNode.parentNode.config.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
|
||||
@@ -109,7 +115,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
if (outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.code.codeName === undefined) {
|
||||
if (outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.config.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Data Mine witn no codeName defined. Data Mine = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode.parentNode.parentNode));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
@@ -126,19 +132,19 @@
|
||||
*/
|
||||
for (let i = 0; i < dataDependencies.length; i++) {
|
||||
|
||||
let dataFile
|
||||
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]
|
||||
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
|
||||
singularVariableName = dataDependencyNode.referenceParent.parentNode.config.singularVariableName
|
||||
/* Transform the raw data into JSON objects */
|
||||
jsonData = jsonifyDataFile(dataFile, recordDefinition)
|
||||
/* Add the calculated properties */
|
||||
@@ -147,7 +153,7 @@
|
||||
} else {
|
||||
inputData = jsonData
|
||||
}
|
||||
products[dataDependencyNode.referenceParent.parentNode.code.pluralVariableName] = inputData
|
||||
products[dataDependencyNode.referenceParent.parentNode.config.pluralVariableName] = inputData
|
||||
|
||||
/* The main dependency is defined as the first dependency processed. */
|
||||
if (mainDependency.records === undefined) {
|
||||
@@ -171,8 +177,8 @@
|
||||
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]
|
||||
if (property.config.isCalculated !== true) {
|
||||
record[property.config.codeName] = dataFile[i][j]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,13 +238,13 @@
|
||||
/* 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.config.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
|
||||
currentRecord[property.config.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))
|
||||
@@ -271,7 +277,7 @@
|
||||
interExecutionMemory,
|
||||
processingDailyFiles,
|
||||
currentDay
|
||||
) {
|
||||
) {
|
||||
|
||||
/*
|
||||
This function has as an input the products object, with all the information
|
||||
@@ -280,11 +286,12 @@
|
||||
a new set of information.
|
||||
*/
|
||||
|
||||
let lastInstantOfTheDay
|
||||
let lastInstantOfTheDay
|
||||
let yesterday = {}
|
||||
let system = { // These are the available system variables to be used in User Code and Formulas
|
||||
timeFrame: timeFrame,
|
||||
ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS
|
||||
ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS,
|
||||
ONE_MIN_IN_MILISECONDS: ONE_MIN_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 = []
|
||||
@@ -306,7 +313,7 @@
|
||||
let dataDependencyMap = new Map()
|
||||
for (let j = 0; j < dataDependecyArray.length; j++) {
|
||||
let record = dataDependecyArray[j]
|
||||
let key = record.begin.toString() + '-' + record.end.toString()
|
||||
let key = record.begin.toString() + '-' + record.end.toString()
|
||||
dataDependencyMap.set(key, record)
|
||||
}
|
||||
dataDependencies[dataDependencyName] = dataDependencyMap
|
||||
@@ -314,7 +321,7 @@
|
||||
}
|
||||
|
||||
function getElement(dependencyName, currentRecordPrimaryDataDependency) {
|
||||
let key = currentRecordPrimaryDataDependency.begin.toString() + '-' + currentRecordPrimaryDataDependency.end.toString()
|
||||
let key = currentRecordPrimaryDataDependency.begin.toString() + '-' + currentRecordPrimaryDataDependency.end.toString()
|
||||
return dataDependencies[dependencyName].get(key)
|
||||
}
|
||||
|
||||
@@ -342,7 +349,7 @@
|
||||
}
|
||||
else {
|
||||
/* We override the initialization, since the valid stuff is already at the Inter Execution Memory */
|
||||
variable = JSON.parse(JSON.stringify(interExecutionMemory[productName].variable))
|
||||
variable = JSON.parse(JSON.stringify(interExecutionMemory[productName].variable))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,13 +387,13 @@
|
||||
/* 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.config.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
|
||||
currentRecord[property.config.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))
|
||||
@@ -467,13 +474,13 @@
|
||||
let propertySeparator = ""
|
||||
for (let j = 0; j < recordDefinition.properties.length; j++) {
|
||||
let property = recordDefinition.properties[j]
|
||||
if (property.code.isCalculated !== true) {
|
||||
if (property.config.isCalculated !== true) {
|
||||
fileContent = fileContent + propertySeparator
|
||||
if (property.code.isString === true) {
|
||||
if (property.config.isString === true) {
|
||||
fileContent = fileContent + '"'
|
||||
}
|
||||
fileContent = fileContent + record[property.code.codeName]
|
||||
if (property.code.isString === true) {
|
||||
fileContent = fileContent + record[property.config.codeName]
|
||||
if (property.config.isString === true) {
|
||||
fileContent = fileContent + '"'
|
||||
}
|
||||
if (propertySeparator === "") { propertySeparator = ","; }
|
||||
|
||||
-551
@@ -1,551 +0,0 @@
|
||||
exports.newContext = function newContext(BOT, logger, UTILITIES) {
|
||||
|
||||
let bot = BOT;
|
||||
|
||||
const MODULE_NAME = "Context";
|
||||
|
||||
/*
|
||||
|
||||
This module deals with keeping the context between different executions of the bot. Conceptually this context is divided in 3 main parts:
|
||||
|
||||
I. The non-business information which helps the mechanisms of giving continuety to the bots execution over time. This information goes in a file
|
||||
called the Status Report, and there is a module, child of this one called Status Report that deals with loading and saving the contents of that file.
|
||||
|
||||
II. The business information around the bot execution, including its balance, positions at exchanges, trades executed and many other things. These
|
||||
are platform data mantained on behalf of the executing bot. All these is kept in one file per execution called the Execution Context. The collection
|
||||
of all these files can later reconstruct the vital business information the bot had at each moment in time.
|
||||
|
||||
II. Execution of any bot cannot be guaranteed that will be on fixed interval of times. We need an index of all executions that points to the detailed files
|
||||
with all the business informatino the bot had each time it executed. We call this index the Execution History and there is one file to store it.
|
||||
|
||||
*/
|
||||
|
||||
let thisObject = {
|
||||
statusReport: undefined, // Here is the information that defines which was the last sucessfull execution and some other details.
|
||||
executionHistory: [], // This is the record of bot execution.
|
||||
executionContext: undefined, // Here is the business information of the last execution of this bot process.
|
||||
newHistoryRecord : {
|
||||
date: undefined,
|
||||
buyAvgRate: 0,
|
||||
sellAvgRate: 0,
|
||||
lastSellRate: 0,
|
||||
sellExecRate: 0,
|
||||
lastBuyRate: 0,
|
||||
buyExecRate: 0,
|
||||
marketRate: 0,
|
||||
newPositions: 0,
|
||||
newTrades: 0,
|
||||
movedPositions: 0,
|
||||
profitsBaseAsset: 0,
|
||||
profitsQuotedAsset: 0,
|
||||
combinedProfitsA: 0,
|
||||
combinedProfitsB: 0,
|
||||
messageRelevance: 0,
|
||||
messageTitle: "",
|
||||
messageBody: ""
|
||||
},
|
||||
initialize: initialize,
|
||||
saveThemAll: saveThemAll,
|
||||
extraData: []
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
During the process we will create a new History Record. This will go to the Context History file which essentially mantains an
|
||||
index of all the bots executions. This file will later be plotted by the bot s plotter on the timeline, allowing end users to
|
||||
know where there is information related to the actions taken by the bot.
|
||||
|
||||
*/
|
||||
|
||||
let statusReportModule;
|
||||
|
||||
/* Utilities needed. */
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(logger);
|
||||
|
||||
/* Storage account to be used here. */
|
||||
|
||||
const FILE_STORAGE = require('./FileStorage.js');
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
let statusDependencies;
|
||||
|
||||
let runIndex; // This is the index for this run and depends on the startMode.
|
||||
let sessionPath = ''
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize(pStatusDependencies, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
|
||||
|
||||
statusDependencies = pStatusDependencies;
|
||||
|
||||
if (bot.SESSION !== undefined) {
|
||||
sessionPath = bot.SESSION.folderName + "/"
|
||||
}
|
||||
|
||||
/*
|
||||
Here we get the positions the bot did and that are recorded at the bot storage account. We will use them through out the rest
|
||||
of the process.
|
||||
*/
|
||||
thisObject.newHistoryRecord.date = bot.processDatetime;
|
||||
|
||||
getStatusReport(onDone);
|
||||
|
||||
function onDone(err) {
|
||||
try {
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> onDone -> Execution finished well."); }
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
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, "[ERROR] initialize -> onDone -> Retry Later. Requesting Execution Retry.");
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> Operation Failed. Aborting the process.");
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> Operation Failed with custom response.");
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> err = " + JSON.stringify(err));
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> err = "+ err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function getStatusReport(callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getStatusReport -> Entering function."); }
|
||||
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + "Context" + "-" + bot.dataSetVersion;
|
||||
|
||||
statusReportModule = statusDependencies.statusReports.get(key);
|
||||
thisObject.statusReport = statusReportModule.file;
|
||||
|
||||
/* The context is created in 2 situations: 1) when at the bot config is set not to continue using the same context after a new execution. 2) when the status report does not exist. */
|
||||
|
||||
if (bot.hasTheBotJustStarted === true || thisObject.statusReport.runs === undefined) {
|
||||
|
||||
createConext(callBack);
|
||||
|
||||
} else {
|
||||
|
||||
runIndex = thisObject.statusReport.runs.length - 1;
|
||||
|
||||
getExecutionHistory(callBack);
|
||||
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getStatusReport -> err = "+ err.stack);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function getExecutionHistory(callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getExecutionHistory -> Entering function."); }
|
||||
|
||||
let fileName = "Execution.History." + bot.startMode + "." + runIndex + ".json";
|
||||
let filePath = bot.filePathRoot + "/Output/" + sessionPath + "Trading-Process/" + fileName;
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionHistory -> onFileReceived -> err = "+ JSON.stringify(err));
|
||||
callBack(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logContent === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] initialize -> getExecutionHistory -> onFileReceived -> Content received = " + text);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
thisObject.executionHistory = JSON.parse(text);
|
||||
|
||||
/* Move some values to the new record, in case there are no transactions that re-calculate them. */
|
||||
|
||||
thisObject.newHistoryRecord.buyAvgRate = thisObject.executionHistory[thisObject.executionHistory.length-1][1];
|
||||
thisObject.newHistoryRecord.sellAvgRate = thisObject.executionHistory[thisObject.executionHistory.length - 1][2];
|
||||
|
||||
getExecutionContext(callBack);
|
||||
|
||||
} catch (err) {
|
||||
|
||||
/*
|
||||
|
||||
It might happen that the file content is corrupt or it does not exist. The bot can not run without an Execution Hitory,
|
||||
since it is risky to ignore its own history unless it is its first execution in this mode ever.
|
||||
|
||||
*/
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionHistory -> onFileReceived -> Bot cannot execute without the Execution History. -> Err = " + err.message);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionHistory -> err = "+ err.stack);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function getExecutionContext(callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> getExecutionContext -> Entering function."); }
|
||||
|
||||
let date;
|
||||
|
||||
date = new Date(thisObject.statusReport.runs[runIndex].lastExecution);
|
||||
thisObject.statusReport.runs[runIndex].lastExecution = bot.processDatetime;
|
||||
thisObject.statusReport.runs[runIndex].endDatetime = bot.processDatetime;
|
||||
|
||||
let fileName = "/Execution.Context." + bot.startMode + "." + runIndex + ".json";
|
||||
let dateForPath = date.getUTCFullYear() + '/' + utilities.pad(date.getUTCMonth() + 1, 2) + '/' + utilities.pad(date.getUTCDate(), 2) + '/' + utilities.pad(date.getUTCHours(), 2) + '/' + utilities.pad(date.getUTCMinutes(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + sessionPath + "Trading-Process/" + dateForPath + fileName;
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> onFileReceived -> err = "+ err.stack);
|
||||
callBack(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logContent === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] initialize -> getExecutionContext -> onFileReceived -> Content received = " + text);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
thisObject.executionContext = JSON.parse(text);
|
||||
thisObject.executionContext.transactions = []; // We record here the transactions that happened duting this execution.
|
||||
|
||||
/* Update the new History Record, in case there are no trades during this execution that updates it. */
|
||||
|
||||
thisObject.newHistoryRecord.profitsBaseAsset = thisObject.executionContext.profits.baseAsset;
|
||||
thisObject.newHistoryRecord.profitsQuotedAsset = thisObject.executionContext.profits.quotedAsset;
|
||||
|
||||
thisObject.newHistoryRecord.combinedProfitsA = thisObject.executionContext.combinedProfits.baseAsset;
|
||||
thisObject.newHistoryRecord.combinedProfitsB = thisObject.executionContext.combinedProfits.quotedAsset;
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
|
||||
/*
|
||||
|
||||
It might happen that the file content is corrupt or it does not exist. The bot can not run without a Status Report,
|
||||
since it is risky to ignore its own execution history. Except when the bot is running for the fist time in this mode,
|
||||
an execution context file with the right format is needed.
|
||||
|
||||
*/
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> onFileReceived -> Response from storage. -> Text = " + text);
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> onFileReceived -> Bot cannot execute without the Execution Context. -> Err = " + err.message);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> err = "+ err.stack);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function createConext(callBack) {
|
||||
|
||||
try {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> createConext -> Entering function."); }
|
||||
/*
|
||||
|
||||
When the bot is executed for the very first time, there are a few files that do not exist and need to be created, and that
|
||||
content is what we are going to set up now.
|
||||
|
||||
*/
|
||||
|
||||
if (thisObject.statusReport.runs === undefined) { // This means that the Status Report does not exist.
|
||||
|
||||
thisObject.statusReport.runs = [];
|
||||
}
|
||||
|
||||
let runContent = {
|
||||
beginDatetime: bot.processDatetime,
|
||||
endDatetime: bot.processDatetime,
|
||||
lastExecution: bot.processDatetime
|
||||
};
|
||||
|
||||
thisObject.statusReport.runs.push(runContent);
|
||||
runIndex = thisObject.statusReport.runs.length - 1;
|
||||
|
||||
thisObject.executionHistory = [];
|
||||
|
||||
if (bot.VALUES_TO_USE.initialBalanceA === undefined || bot.VALUES_TO_USE.initialBalanceB === undefined) { throw new Error("Global Variables INITIAL_BALANCE_A and INITIAL_BALANCE_B cannot be undefined.") }
|
||||
|
||||
const INITIAL_BALANCE_A = Number(bot.VALUES_TO_USE.initialBalanceB); // NOTE THAT THIS IS INVERTED BECAUSE OF POLONIEX THAT IS THE ONLY EXCHANGE SUPPORTED RIGHT NOW
|
||||
const INITIAL_BALANCE_B = Number(bot.VALUES_TO_USE.initialBalanceA);
|
||||
|
||||
|
||||
thisObject.executionContext = {
|
||||
initialBalance: { // This is used to calculate profits.
|
||||
baseAsset: INITIAL_BALANCE_A,
|
||||
quotedAsset: INITIAL_BALANCE_B
|
||||
},
|
||||
balance: { // This is the total balance that includes positions at the order book + funds available to be traded.
|
||||
baseAsset: INITIAL_BALANCE_A,
|
||||
quotedAsset: INITIAL_BALANCE_B // It starts with the initial initialBalance.
|
||||
},
|
||||
availableBalance: { // This is the balance the bot has at any moment in time available to be traded (not in positions at the order book).
|
||||
baseAsset: INITIAL_BALANCE_A,
|
||||
quotedAsset: INITIAL_BALANCE_B // It starts with the initial initialBalance.
|
||||
},
|
||||
profits: {
|
||||
baseAsset: 0,
|
||||
quotedAsset: 0
|
||||
},
|
||||
combinedProfits: {
|
||||
baseAsset: 0,
|
||||
quotedAsset: 0
|
||||
},
|
||||
positions: [],
|
||||
transactions: []
|
||||
};
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> createConext -> err = "+ err.stack);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function saveThemAll(callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> Entering function."); }
|
||||
|
||||
writeExecutionContext(onDone);
|
||||
|
||||
function onDone(err) {
|
||||
try {
|
||||
|
||||
switch (err.result) {
|
||||
case global.DEFAULT_OK_RESPONSE.result: {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> onDone -> Execution finished well."); }
|
||||
|
||||
bot.hasTheBotJustStarted = false;
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
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, "[ERROR] saveThemAll -> onDone -> Retry Later. Requesting Execution Retry.");
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> onDone -> Operation Failed. Aborting the process.");
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> onDone -> err = "+ err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function writeExecutionContext(callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExecutionContext -> Entering function."); }
|
||||
|
||||
let fileName = "/Execution.Context." + bot.startMode + "." + runIndex +".json";
|
||||
let dateForPath = bot.processDatetime.getUTCFullYear() + '/' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.processDatetime.getUTCDate(), 2) + '/' + utilities.pad(bot.processDatetime.getUTCHours(), 2) + '/' + utilities.pad(bot.processDatetime.getUTCMinutes(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + sessionPath + "Trading-Process/" + dateForPath + fileName;
|
||||
let fileContent = JSON.stringify(thisObject.executionContext);
|
||||
|
||||
if(fileContent === undefined){
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExecutionContext -> executionContext is undefined.");
|
||||
callBackFunction(global.DEFAULT_ERROR_RESPONSE);
|
||||
}
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logContent === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExecutionContext -> fileContent = " + fileContent); }
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
|
||||
function onFileCreated(err) {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExecutionContext -> onFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExecutionContext -> onFileCreated -> err = "+ err.stack);
|
||||
callBack(err);
|
||||
return;
|
||||
}
|
||||
|
||||
writeExucutionHistory(callBack);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExecutionContext -> err = "+ err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function writeExucutionHistory(callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExucutionHistory -> Entering function."); }
|
||||
|
||||
let fileName = "Execution.History." + bot.startMode + "." + runIndex + ".json";
|
||||
let filePath = bot.filePathRoot + "/Output/" + sessionPath + "Trading-Process/" + fileName;
|
||||
|
||||
let newRecord = [
|
||||
thisObject.newHistoryRecord.date.valueOf(),
|
||||
thisObject.newHistoryRecord.buyAvgRate,
|
||||
thisObject.newHistoryRecord.sellAvgRate,
|
||||
|
||||
thisObject.newHistoryRecord.lastSellRate,
|
||||
thisObject.newHistoryRecord.sellExecRate,
|
||||
thisObject.newHistoryRecord.lastBuyRate,
|
||||
thisObject.newHistoryRecord.buyExecRate,
|
||||
|
||||
thisObject.newHistoryRecord.marketRate,
|
||||
thisObject.newHistoryRecord.newPositions,
|
||||
thisObject.newHistoryRecord.newTrades,
|
||||
thisObject.newHistoryRecord.movedPositions,
|
||||
thisObject.newHistoryRecord.profitsBaseAsset,
|
||||
thisObject.newHistoryRecord.profitsQuotedAsset,
|
||||
thisObject.newHistoryRecord.combinedProfitsA,
|
||||
thisObject.newHistoryRecord.combinedProfitsB,
|
||||
|
||||
thisObject.newHistoryRecord.messageRelevance,
|
||||
thisObject.newHistoryRecord.messageTitle,
|
||||
thisObject.newHistoryRecord.messageBody,
|
||||
thisObject.extraData
|
||||
];
|
||||
|
||||
thisObject.executionHistory.push(newRecord);
|
||||
|
||||
let fileContent = JSON.stringify(thisObject.executionHistory);
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
|
||||
function onFileCreated(err) {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExucutionHistory -> onFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> onFileCreated -> err = "+ err.stack);
|
||||
callBack(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logContent === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExucutionHistory -> onFileCreated -> Content written = " + fileContent);
|
||||
}
|
||||
|
||||
/* Here we will write the file containing the max sequence number. */
|
||||
|
||||
fileContent = runIndex;
|
||||
fileName = "Execution.History." + bot.startMode + "." + "Sequence" + ".json";
|
||||
filePath = bot.filePathRoot + "/Output/" + sessionPath + "Trading-Process/" + fileName;
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onSequenceFileCreated);
|
||||
|
||||
function onSequenceFileCreated(err) {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExucutionHistory -> onFileCreated -> onSequenceFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> onFileCreated -> onSequenceFileCreated -> err = "+ err.stack);
|
||||
callBack(err);
|
||||
return;
|
||||
}
|
||||
|
||||
writeStatusReport(callBack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> err = "+ err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function writeStatusReport(callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeStatusReport -> Entering function."); }
|
||||
|
||||
statusReportModule.file = thisObject.statusReport;
|
||||
statusReportModule.save(callBack);
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeStatusReport -> err = "+ err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] saveThemAll -> Error = " + err.message);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function truncDecimals(pFloatValue, pDecimals) {
|
||||
|
||||
if (!pDecimals) pDecimals = 8; // Default value
|
||||
|
||||
return parseFloat(parseFloat(pFloatValue).toFixed(pDecimals));
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
+15
-15
@@ -16,7 +16,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
/* Storage account to be used here. */
|
||||
|
||||
const FILE_STORAGE = require('./FileStorage.js');
|
||||
let fileStorage
|
||||
let fileStorage
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -36,7 +36,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
return
|
||||
}
|
||||
|
||||
if (thisObject.node.code.codeName === undefined) {
|
||||
if (thisObject.node.config.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> Dataset witn no codeName defined -> Product Dataset = " + JSON.stringify(thisObject.node));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
@@ -48,7 +48,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
return
|
||||
}
|
||||
|
||||
if (thisObject.node.parentNode.code.codeName === undefined) {
|
||||
if (thisObject.node.parentNode.config.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> Product Definition witn no codeName defined -> Product Definition = " + JSON.stringify(thisObject.node.parentNode));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
@@ -60,7 +60,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
return
|
||||
}
|
||||
|
||||
if (thisObject.node.parentNode.parentNode.code.codeName === undefined) {
|
||||
if (thisObject.node.parentNode.parentNode.config.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> Bot witn no codeName defined. Bot = " + JSON.stringify(thisObject.node.parentNode.parentNode));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
@@ -72,14 +72,14 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
return
|
||||
}
|
||||
|
||||
if (thisObject.node.parentNode.parentNode.parentNode.code.codeName === undefined) {
|
||||
if (thisObject.node.parentNode.parentNode.parentNode.config.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> Data Mine witn no codeName defined. Data Mine = " + JSON.stringify(thisObject.node.parentNode.parentNode.parentNode));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
|
||||
/* Now we will see where do we need to fetch this data from. */
|
||||
let network = global.TASK_NETWORK
|
||||
let network = global.TASK_NETWORK
|
||||
let datasetProductDefinition = thisObject.node.parentNode
|
||||
|
||||
for (let i = 0; i < network.networkNodes.length; i++) {
|
||||
@@ -102,9 +102,9 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
if (datasetProductDefinition.id === productDefinition.id) {
|
||||
|
||||
/* We found where the data is located on the network. */
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving data from " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webPort + '.'); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving data from " + networkNode.name + " -> host = " + networkNode.config.host + ' -> port = ' + networkNode.config.webPort + '.'); }
|
||||
|
||||
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.code.host, networkNode.code.webPort);
|
||||
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.config.host, networkNode.config.webPort);
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return
|
||||
}
|
||||
@@ -133,9 +133,9 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
if (datasetProductDefinition.id === productDefinition.id) {
|
||||
|
||||
/* We found where the data is located on the network. */
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving data from " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webPort + '.'); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving data from " + networkNode.name + " -> host = " + networkNode.config.host + ' -> port = ' + networkNode.config.webPort + '.'); }
|
||||
|
||||
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.code.host, networkNode.code.webPort);
|
||||
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.config.host, networkNode.config.webPort);
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return
|
||||
}
|
||||
@@ -155,7 +155,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -173,8 +173,8 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] getTextFile -> Entering function."); }
|
||||
|
||||
let dataMineCodeName = thisObject.node.parentNode.parentNode.parentNode.code.codeName
|
||||
let botCodeName = thisObject.node.parentNode.parentNode.code.codeName
|
||||
let dataMineCodeName = thisObject.node.parentNode.parentNode.parentNode.config.codeName
|
||||
let botCodeName = thisObject.node.parentNode.parentNode.config.codeName
|
||||
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + dataMineCodeName + "/" + botCodeName;
|
||||
let filePath = filePathRoot + "/Output/" + pFolderPath;
|
||||
@@ -191,7 +191,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] 'getTextFile' -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] 'getTextFile' -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -232,7 +232,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] 'createTextFile' -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] 'createTextFile' -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -34,7 +34,7 @@ exports.newDebugLog = function newDebugLog() {
|
||||
disableLogging = pdisableLogging
|
||||
|
||||
} catch (err) {
|
||||
console.log("[ERROR] Debug Log -> initialize -> err = "+ err.stack);
|
||||
console.log("[ERROR] Debug Log -> initialize -> err = " + err.stack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,12 +53,12 @@ exports.newDebugLog = function newDebugLog() {
|
||||
date = date.getUTCFullYear() + '-' + strPad(date.getUTCMonth() + 1, 2, "0") + '-' + strPad(date.getUTCDate(), 2, "0");
|
||||
|
||||
console.log(new Date().toISOString() + " " + strPad(thisObject.bot.exchange, 20) + " " + strPad(thisObject.bot.market.baseAsset + '/' + thisObject.bot.market.quotedAsset, 10) + " " + strPad(pBot, 30) + " " + strPad(pProcess, 30)
|
||||
+ " Internal Loop # " + strPad(internalLoopCounter + 1, 8) + " " + strPad(date, 30) + " " + strPad(percentage, 10))
|
||||
+ " Internal Loop # " + strPad(internalLoopCounter + 1, 8) + " " + strPad(date, 30) + " " + strPad(percentage, 10))
|
||||
|
||||
persist();
|
||||
|
||||
function strPad(str, max, fill) {
|
||||
if (fill === undefined) {fill = " "}
|
||||
if (fill === undefined) { fill = " " }
|
||||
str = str.toString();
|
||||
return str.length < max ? strPad(fill + str, max) : str;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ exports.newDebugLog = function newDebugLog() {
|
||||
/* Here we actually write the content of the in-memory log to a file */
|
||||
|
||||
try {
|
||||
if (accumulatedLog === "[") {return} // nothing to persist at the moment.
|
||||
if (accumulatedLog === "[") { return } // nothing to persist at the moment.
|
||||
|
||||
internalLoopCounter++;
|
||||
|
||||
@@ -82,7 +82,7 @@ exports.newDebugLog = function newDebugLog() {
|
||||
let filePath = thisObject.bot.filePathRoot + "/Logs/" + thisObject.bot.process + "/"
|
||||
|
||||
if (thisObject.bot.SESSION !== undefined) {
|
||||
filePath = filePath + thisObject.bot.SESSION.folderName + "/" + executionDatetime;
|
||||
filePath = filePath + thisObject.bot.SESSION.folderName + "/" + executionDatetime;
|
||||
} else {
|
||||
filePath = filePath + executionDatetime;
|
||||
}
|
||||
@@ -102,32 +102,32 @@ exports.newDebugLog = function newDebugLog() {
|
||||
writeLog();
|
||||
|
||||
/* This is the implementation of the mechanism to auto-mantain logs. */
|
||||
if (contentToPersist.indexOf('[ERROR]') < 0) {
|
||||
if (contentToPersist.indexOf('[ERROR]') < 0 && contentToPersist.indexOf('[PERSIST]') < 0) {
|
||||
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)
|
||||
/* Will delete this file only if it does not contains ERROR inside. */
|
||||
let fileContent = fileStorage.getTextFile(fileToDelete, onGetFile, true)
|
||||
let fileContent = fileStorage.getTextFile(fileToDelete, onGetFile, true)
|
||||
function onGetFile(err, fileContent) {
|
||||
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
|
||||
if (fileContent.indexOf("ERROR") < 0) {
|
||||
/* Logs will only be deleted when they contain no ERROR in them. */
|
||||
fileStorage.deleteTextFile(fileToDelete);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fileStorage.deleteTextFile(fileToDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function writeLog() {
|
||||
|
||||
fileStorage.createTextFile(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);
|
||||
console.log("[ERROR] DebugLog -> persist -> onInizialized -> onFileCreated -> err = " + err.message);
|
||||
setTimeout(writeLog, 10000); // Lets retry until we make it.
|
||||
return;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ exports.newDebugLog = function newDebugLog() {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("[ERROR] DebugLog -> persist -> err = "+ err.stack);
|
||||
console.log("[ERROR] DebugLog -> persist -> err = " + err.stack);
|
||||
console.log("[ERROR] DebugLog -> persist -> onInizialized -> contentToPersist = " + contentToPersist);
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ exports.newDebugLog = function newDebugLog() {
|
||||
accumulatedLog = accumulatedLog + logLine;
|
||||
|
||||
} catch (err) {
|
||||
console.log("[ERROR] DebugLog -> write -> err = "+ err.stack);
|
||||
console.log("[ERROR] DebugLog -> write -> err = " + err.stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+40
-40
@@ -22,11 +22,11 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
deleteTextFile: deleteTextFile
|
||||
}
|
||||
|
||||
return thisObject
|
||||
return thisObject
|
||||
|
||||
function getTextFile(filePath, callBackFunction, noRetry, canUsePrevious) {
|
||||
|
||||
let currentRetryGetTextFile = 0
|
||||
let currentRetryGetTextFile = 0
|
||||
|
||||
recursiveGetTextFile(filePath, callBackFunction, noRetry, canUsePrevious)
|
||||
|
||||
@@ -77,7 +77,7 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
}
|
||||
callBackFunction(customResponse)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fileDoesNotExist = true
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> onFileRead -> File does not exist. Retrying. ')
|
||||
@@ -106,7 +106,7 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
if (mustBeJason === false) {
|
||||
/* In this case there is nothing else to check. */
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, text.toString())
|
||||
return
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -117,7 +117,7 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
|
||||
/* The file was correctly read and could be parsed. */
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, text.toString())
|
||||
return
|
||||
return
|
||||
|
||||
} catch (err) {
|
||||
|
||||
@@ -140,11 +140,11 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> onFileRead -> canUsePrevious -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/* Returning the previous file */
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE, text.toString())
|
||||
return
|
||||
return
|
||||
}
|
||||
} else {
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> onFileRead -> Could read the file, but could not parse it as it is not a valid JSON.')
|
||||
@@ -153,12 +153,12 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
setTimeout(retry, retryTimeToUse)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> Error writing file -> file = ' + fileLocation)
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> Error writing file -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> Error reading file -> file = ' + fileLocation)
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> Error reading file -> err = ' + err.stack)
|
||||
retry()
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> createTextFile -> onFileWriten -> onUnlinked -> Error deleting file -> err = ' + err.stack)
|
||||
setTimeout(retry, retryTimeToUse)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/* Rename de Original into Previous */
|
||||
fs.rename(fileLocation, fileLocation + '.Previous.json', onOriginalRenamed)
|
||||
@@ -266,7 +266,7 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> createTextFile -> onFileWriten -> onUnlinked -> onOriginalRenamed -> Error renaming original file -> file = ' + fileLocation)
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> createTextFile -> onFileWriten -> onUnlinked -> onOriginalRenamed -> Error renaming original file -> err = ' + err.stack)
|
||||
setTimeout(retry, retryTimeToUse)
|
||||
return
|
||||
return
|
||||
}
|
||||
|
||||
/* Rename de Temp into Original */
|
||||
@@ -282,13 +282,13 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
/* In this case, there is no need to keep a copy of the file being replaced, so we just delete and that's it. */
|
||||
fs.unlink(fileLocation , onUnlinked)
|
||||
fs.unlink(fileLocation, onUnlinked)
|
||||
|
||||
function onUnlinked(err) {
|
||||
let code = ''
|
||||
@@ -296,11 +296,11 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
code = err.code
|
||||
}
|
||||
if (code !== '' && code !== 'ENOENT') {
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> createTextFile -> onFileWriten -> onUnlinked -> Error deleting file -> file = ' + fileLocation )
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> createTextFile -> onFileWriten -> onUnlinked -> Error deleting file -> file = ' + fileLocation)
|
||||
logger.write(MODULE_NAME, '[WARN] FileStorage -> createTextFile -> onFileWriten -> onUnlinked -> Error deleting file -> err = ' + err.stack)
|
||||
setTimeout(retry, retryTimeToUse)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/* Rename de Temp into Original */
|
||||
fs.rename(fileLocation + '.tmp', fileLocation, onTempRenamed)
|
||||
@@ -406,33 +406,33 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
|
||||
/* Function to create folders of missing folders at any path. */
|
||||
function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
|
||||
const sep = '/';
|
||||
const initDir = path.isAbsolute(targetDir) ? sep : '';
|
||||
const baseDir = isRelativeToScript ? __dirname : '.';
|
||||
const sep = '/';
|
||||
const initDir = path.isAbsolute(targetDir) ? sep : '';
|
||||
const baseDir = isRelativeToScript ? __dirname : '.';
|
||||
|
||||
return targetDir.split(sep).reduce((parentDir, childDir) => {
|
||||
const curDir = path.resolve(baseDir, parentDir, childDir);
|
||||
try {
|
||||
const fs = require('fs')
|
||||
fs.mkdirSync(curDir);
|
||||
} catch (err) {
|
||||
if (err.code === 'EEXIST') { // curDir already exists!
|
||||
return curDir;
|
||||
}
|
||||
return targetDir.split(sep).reduce((parentDir, childDir) => {
|
||||
const curDir = path.resolve(baseDir, parentDir, childDir);
|
||||
try {
|
||||
const fs = require('fs')
|
||||
fs.mkdirSync(curDir);
|
||||
} catch (err) {
|
||||
if (err.code === 'EEXIST') { // curDir already exists!
|
||||
return curDir;
|
||||
}
|
||||
|
||||
// To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
|
||||
if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
|
||||
throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`);
|
||||
}
|
||||
// To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
|
||||
if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
|
||||
throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`);
|
||||
}
|
||||
|
||||
const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
|
||||
if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) {
|
||||
throw err; // Throw if it's just the last created dir.
|
||||
}
|
||||
}
|
||||
const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
|
||||
if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) {
|
||||
throw err; // Throw if it's just the last created dir.
|
||||
}
|
||||
}
|
||||
|
||||
return curDir;
|
||||
}, initDir);
|
||||
return curDir;
|
||||
}, initDir);
|
||||
}
|
||||
|
||||
function getFileViaHTTP(filePath, callback, callBackFunction) {
|
||||
@@ -455,7 +455,7 @@ exports.newFileStorage = function newFileStorage(logger, host, port) {
|
||||
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> onError -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> onError -> Failed to fetch file via HTTP. Will retry later. ");
|
||||
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
|
||||
})
|
||||
})
|
||||
|
||||
function onResponse(response) {
|
||||
|
||||
|
||||
+9
-9
@@ -65,7 +65,7 @@
|
||||
if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) { return }
|
||||
|
||||
let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets
|
||||
if (commons.validateOutputDatasets(outputDatasets, callBackFunction) !== true) { return }
|
||||
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, timeFrame)
|
||||
@@ -86,7 +86,7 @@
|
||||
*/
|
||||
|
||||
recordDefinition = outputDatasetNode.referenceParent.parentNode.record
|
||||
singularVariableName = outputDatasetNode.referenceParent.parentNode.code.singularVariableName
|
||||
singularVariableName = outputDatasetNode.referenceParent.parentNode.config.singularVariableName
|
||||
|
||||
/* Check Irregular Periods */
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
recordDefinition,
|
||||
outputDatasetNode.referenceParent.parentNode.dataBuilding,
|
||||
singularVariableName,
|
||||
outputDatasetNode.referenceParent.parentNode.code.codeName,
|
||||
outputDatasetNode.referenceParent.parentNode.config.codeName,
|
||||
timeFrame,
|
||||
timeFrameLabel,
|
||||
resultsWithIrregularPeriods,
|
||||
@@ -118,14 +118,14 @@
|
||||
} else {
|
||||
outputData = jsonData
|
||||
}
|
||||
products[outputDatasetNode.referenceParent.parentNode.code.pluralVariableName] = outputData
|
||||
products[outputDatasetNode.referenceParent.parentNode.config.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 outputData = products[outputDatasetNode.referenceParent.parentNode.config.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 = {}
|
||||
|
||||
@@ -136,10 +136,10 @@
|
||||
|
||||
/* 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.dataMine = outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.code.codeName
|
||||
contextSummary.dataset = outputDatasetNode.referenceParent.config.codeName
|
||||
contextSummary.product = outputDatasetNode.referenceParent.parentNode.config.codeName
|
||||
contextSummary.bot = outputDatasetNode.referenceParent.parentNode.parentNode.config.codeName
|
||||
contextSummary.dataMine = outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.config.codeName
|
||||
|
||||
/* This stuff is still hardcoded and unresolved. */
|
||||
contextSummary.botVersion = {
|
||||
|
||||
+45
-186
@@ -41,7 +41,7 @@
|
||||
dataDependenciesModule = pDataDependencies;
|
||||
processConfig = pProcessConfig;
|
||||
|
||||
let USER_BOT_MODULE = require("./TradingBot")
|
||||
let USER_BOT_MODULE = require("./Trading/TradingBot")
|
||||
|
||||
botInstance = USER_BOT_MODULE.newTradingBot(bot, logger, UTILITIES, FILE_STORAGE);
|
||||
botInstance.initialize(exchangeAPI, callBackFunction);
|
||||
@@ -57,7 +57,7 @@
|
||||
multiPeriodDataFiles = undefined
|
||||
statusDependencies = undefined
|
||||
dataDependenciesModule = undefined
|
||||
botInstance.finalize()
|
||||
botInstance.finalize()
|
||||
botInstance = undefined
|
||||
fileStorage = undefined
|
||||
processConfig = undefined
|
||||
@@ -71,7 +71,7 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
|
||||
|
||||
let currentTimeFrame
|
||||
let currentTimeFrameLabel
|
||||
let currentTimeFrameLabel
|
||||
|
||||
let market = bot.market;
|
||||
let botNeverRan = true;
|
||||
@@ -86,7 +86,7 @@
|
||||
|
||||
let previousDay; // Holds the date of the previous day relative to the processing date.
|
||||
|
||||
let interExecutionMemoryArray = [];
|
||||
let variable
|
||||
|
||||
getContextVariables();
|
||||
|
||||
@@ -101,12 +101,11 @@
|
||||
let statusReport;
|
||||
|
||||
/* We are going to use the start date as beging of market date. */
|
||||
contextVariables.dateBeginOfMarket = bot.VALUES_TO_USE.timeRange.initialDatetime
|
||||
contextVariables.dateBeginOfMarket = bot.VALUES_TO_USE.timeRange.initialDatetime
|
||||
|
||||
/*
|
||||
Here we get the status report from the bot who knows which is the end of the market.
|
||||
*/
|
||||
|
||||
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.
|
||||
@@ -138,7 +137,6 @@
|
||||
contextVariables.dateEndOfMarket = new Date(thisReport.lastFile.valueOf());
|
||||
|
||||
/* Validation that the data is not up-to-date. */
|
||||
|
||||
if (bot.multiPeriodProcessDatetime.valueOf() - ONE_DAY_IN_MILISECONDS > contextVariables.dateEndOfMarket.valueOf() && bot.SESSION.type !== "Backtesting Session") {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> " + "Head of the market is @ " + contextVariables.dateEndOfMarket); }
|
||||
@@ -150,7 +148,6 @@
|
||||
}
|
||||
|
||||
/* Finally we get our own Status Report. */
|
||||
|
||||
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.
|
||||
@@ -166,26 +163,25 @@
|
||||
}
|
||||
|
||||
thisReport = statusReport.file;
|
||||
variable = thisReport.variable;
|
||||
if (variable === undefined) { variable = {} } // This should happen only when there is no status report
|
||||
|
||||
if (thisReport.lastFile !== undefined) {
|
||||
|
||||
if (bot.hasTheBotJustStarted === true && bot.resumeExecution === false) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Starting from the begining because bot has just started and resume execution was true."); }
|
||||
startFromBegining();
|
||||
return;
|
||||
}
|
||||
|
||||
contextVariables.lastFile = new Date(thisReport.lastFile);
|
||||
interExecutionMemoryArray = thisReport.interExecutionMemoryArray;
|
||||
|
||||
processSingleFiles();
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
In the case when there is no status report, we assume like the last processed file is the one on the date of Begining of Market.
|
||||
We are here becuse either:
|
||||
1. There is no status report
|
||||
2. There is no Last File (this happens on Market Files)
|
||||
*/
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Starting from the begining of the market because own status report not found or lastFile was undefined."); }
|
||||
startFromBegining();
|
||||
@@ -197,19 +193,6 @@
|
||||
contextVariables.lastFile = new Date(contextVariables.dateBeginOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS);
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> startFromBegining -> contextVariables.lastFile = " + contextVariables.lastFile); }
|
||||
|
||||
/*
|
||||
The first time the process is running is the right time to create the data structure that is going to be shared across different executions.
|
||||
This data structure has one object per each timeFrame.
|
||||
*/
|
||||
|
||||
interExecutionMemoryArray = [];
|
||||
|
||||
for (let i = 0; i < global.dailyFilePeriods.length; i++) {
|
||||
let emptyObject = {};
|
||||
interExecutionMemoryArray.push(emptyObject);
|
||||
}
|
||||
|
||||
processSingleFiles();
|
||||
|
||||
}
|
||||
@@ -237,7 +220,6 @@
|
||||
function dependencyLoopBody() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processSingleFiles -> dependencyLoopBody -> Entering function."); }
|
||||
|
||||
let dependency = dataDependenciesModule.nodeArray[dependencyIndex];
|
||||
@@ -249,24 +231,23 @@
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processSingleFiles -> dependencyLoopBody -> getFile -> Entering function."); }
|
||||
|
||||
if (datasetModule.node.code.codeName !== "Single-File") {
|
||||
if (datasetModule.node.config.codeName !== "Single-File") {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
|
||||
if (dataDependenciesModule.isItADepenency('atAnyTimeFrame', datasetModule.node.parentNode.code.singularVariableName) !== true) {
|
||||
if (dataDependenciesModule.isItADepenency('atAnyTimeFrame', datasetModule.node.parentNode.config.singularVariableName) !== true) {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
|
||||
let fileName = "Data.json";
|
||||
let filePath = datasetModule.node.parentNode.code.codeName + '/' + datasetModule.node.code.codeName;
|
||||
let filePath = datasetModule.node.parentNode.config.codeName + '/' + datasetModule.node.config.codeName;
|
||||
datasetModule.getTextFile(filePath, fileName, onFileReceived);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processSingleFiles -> dependencyLoopBody -> getFile -> onFileReceived -> Entering function."); }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processSingleFiles -> dependencyLoopBody -> getFile -> onFileReceived -> text = " + text); }
|
||||
|
||||
@@ -309,22 +290,16 @@
|
||||
function dependencyControlLoop() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processSingleFiles -> dependencyControlLoop -> Entering function."); }
|
||||
|
||||
dependencyIndex++;
|
||||
|
||||
if (dependencyIndex < dataDependenciesModule.nodeArray.length) {
|
||||
|
||||
dependencyLoopBody();
|
||||
|
||||
} else {
|
||||
|
||||
let mapKey = "Single Files"
|
||||
multiPeriodDataFiles.set(mapKey, dataFiles)
|
||||
|
||||
processMarketFiles();
|
||||
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
@@ -344,25 +319,17 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> Entering function."); }
|
||||
|
||||
try {
|
||||
|
||||
let n;
|
||||
|
||||
timeFramesLoop();
|
||||
|
||||
function timeFramesLoop() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> timeFramesLoop -> Entering function."); }
|
||||
|
||||
/*
|
||||
We will iterate through all posible timeFrames.
|
||||
*/
|
||||
|
||||
n = 0 // loop Variable representing each possible period as defined at the timeFrames array.
|
||||
|
||||
timeFramesLoopBody();
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processMarketFiles -> timeFramesLoop -> err = " + err.stack);
|
||||
@@ -371,11 +338,8 @@
|
||||
}
|
||||
|
||||
function timeFramesLoopBody() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> timeFramesLoopBody -> Entering function."); }
|
||||
|
||||
const timeFrame = global.marketFilesPeriods[n][0];
|
||||
const timeFrameLabel = global.marketFilesPeriods[n][1];
|
||||
|
||||
@@ -389,9 +353,7 @@
|
||||
dependencyLoopBody();
|
||||
|
||||
function dependencyLoopBody() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> timeFramesLoopBody -> dependencyLoopBody -> Entering function."); }
|
||||
|
||||
let dependency = dataDependenciesModule.nodeArray[dependencyIndex];
|
||||
@@ -403,26 +365,24 @@
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> timeFramesLoopBody -> dependencyLoopBody -> getFile -> Entering function."); }
|
||||
|
||||
if (dependency.referenceParent.code.codeName !== "Multi-Period-Market") {
|
||||
if (dependency.referenceParent.config.codeName !== "Multi-Period-Market") {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
|
||||
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.code.singularVariableName) !== true) {
|
||||
if (!(bot.VALUES_TO_USE.timeFrame === timeFrameLabel && datasetModule.node.parentNode.code.pluralVariableName === 'candles')) {
|
||||
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) {
|
||||
if (!(bot.VALUES_TO_USE.timeFrame === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let fileName = "Data.json";
|
||||
let filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + timeFrameLabel;
|
||||
let filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel;
|
||||
datasetModule.getTextFile(filePath, fileName, onFileReceived);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> timeFramesLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> Entering function."); }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> timeFramesLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> text = " + text); }
|
||||
|
||||
@@ -433,7 +393,7 @@
|
||||
} else {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processMarketFiles -> timeFramesLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = " + err.message);
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -454,7 +414,6 @@
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processMarketFiles -> timeFramesLoop -> dependencyLoopBody -> err = " + err.stack);
|
||||
@@ -463,24 +422,16 @@
|
||||
}
|
||||
|
||||
function dependencyControlLoop() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> dependencyControlLoop -> Entering function."); }
|
||||
|
||||
dependencyIndex++;
|
||||
|
||||
if (dependencyIndex < dataDependenciesModule.nodeArray.length) {
|
||||
|
||||
dependencyLoopBody();
|
||||
|
||||
} else {
|
||||
|
||||
let mapKey = global.marketFilesPeriods[n][1];
|
||||
multiPeriodDataFiles.set(mapKey, dataFiles)
|
||||
|
||||
timeFramesControlLoop();
|
||||
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
@@ -496,21 +447,13 @@
|
||||
}
|
||||
|
||||
function timeFramesControlLoop() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processMarketFiles -> timeFramesControlLoop -> Entering function."); }
|
||||
|
||||
n++;
|
||||
|
||||
if (n < global.marketFilesPeriods.length) {
|
||||
|
||||
timeFramesLoopBody();
|
||||
|
||||
} else {
|
||||
|
||||
processDailyFiles();
|
||||
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
@@ -518,7 +461,6 @@
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processMarketFiles -> err = " + err.stack);
|
||||
@@ -527,20 +469,14 @@
|
||||
}
|
||||
|
||||
function processDailyFiles() {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> Entering function."); }
|
||||
|
||||
try {
|
||||
|
||||
let n = 0;
|
||||
|
||||
if (currentTimeFrame) {
|
||||
callTheBot()
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
bot.multiPeriodProcessDatetime = new Date(contextVariables.lastFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop.
|
||||
|
||||
advanceTime();
|
||||
|
||||
function advanceTime() {
|
||||
@@ -551,12 +487,11 @@
|
||||
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.multiPeriodProcessDatetime.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
previousDay = new Date(bot.multiPeriodProcessDatetime.valueOf() - ONE_DAY_IN_MILISECONDS);
|
||||
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> advanceTime -> bot.multiPeriodProcessDatetime = " + bot.multiPeriodProcessDatetime); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> advanceTime -> previousDay = " + previousDay); }
|
||||
|
||||
/* Validation that we are not going past the user defined end date. */
|
||||
|
||||
if (bot.multiPeriodProcessDatetime.valueOf() >= bot.VALUES_TO_USE.timeRange.finalDatetime.valueOf()) {
|
||||
|
||||
const logText = "User Defined End Datetime reached @ " + previousDay.getUTCFullYear() + "/" + (previousDay.getUTCMonth() + 1) + "/" + previousDay.getUTCDate() + ".";
|
||||
@@ -565,11 +500,9 @@
|
||||
bot.STOP_SESSION = true
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Validation that we are not going past the head of the market. */
|
||||
|
||||
if (bot.multiPeriodProcessDatetime.valueOf() > contextVariables.dateEndOfMarket.valueOf() + ONE_DAY_IN_MILISECONDS - 1) {
|
||||
|
||||
const logText = "Head of the market found @ " + previousDay.getUTCFullYear() + "/" + (previousDay.getUTCMonth() + 1) + "/" + previousDay.getUTCDate() + ".";
|
||||
@@ -577,7 +510,6 @@
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
checkStopTaskGracefully();
|
||||
@@ -591,20 +523,13 @@
|
||||
function checkStopTaskGracefully() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> checkStopTaskGracefully -> Entering function."); }
|
||||
|
||||
/* Validation that we dont need to stop. */
|
||||
|
||||
if (global.STOP_TASK_GRACEFULLY === true) {
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
checkStopProcessing();
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> checkStopTaskGracefully -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
@@ -612,18 +537,13 @@
|
||||
}
|
||||
|
||||
function checkStopProcessing() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> checkStopProcessing -> Entering function."); }
|
||||
|
||||
/* Validation that we dont need to stop. */
|
||||
|
||||
if (bot.STOP_SESSION === true) {
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
timeFramesLoop();
|
||||
@@ -635,23 +555,16 @@
|
||||
}
|
||||
|
||||
function timeFramesLoop() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoop -> Entering function."); }
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let processingDate = bot.multiPeriodProcessDatetime.getUTCFullYear() + '-' + utilities.pad(bot.multiPeriodProcessDatetime.getUTCMonth() + 1, 2) + '-' + utilities.pad(bot.multiPeriodProcessDatetime.getUTCDate(), 2);
|
||||
bot.processHeartBeat(processingDate)
|
||||
|
||||
bot.processHeartBeat(processingDate)
|
||||
/*
|
||||
|
||||
We will iterate through all posible timeFrames.
|
||||
|
||||
*/
|
||||
|
||||
n = 0 // loop Variable representing each possible period as defined at the timeFrames array.
|
||||
|
||||
timeFramesLoopBody();
|
||||
|
||||
}
|
||||
@@ -662,9 +575,7 @@
|
||||
}
|
||||
|
||||
function timeFramesLoopBody() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> Entering function."); }
|
||||
|
||||
const timeFrame = global.dailyFilePeriods[n][0];
|
||||
@@ -693,9 +604,7 @@
|
||||
dependencyLoopBody();
|
||||
|
||||
function dependencyLoopBody() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> dependencyLoopBody -> Entering function."); }
|
||||
|
||||
let dependency = dataDependenciesModule.nodeArray[dependencyIndex];
|
||||
@@ -715,13 +624,13 @@
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> dependencyLoopBody -> getPreviousFile -> Entering function."); }
|
||||
|
||||
if (dependency.referenceParent.code.codeName !== "Multi-Period-Daily") {
|
||||
if (dependency.referenceParent.config.codeName !== "Multi-Period-Daily") {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
|
||||
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.code.singularVariableName) !== true) {
|
||||
if (!(bot.VALUES_TO_USE.timeFrame === timeFrameLabel && datasetModule.node.parentNode.code.pluralVariableName === 'candles')) {
|
||||
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) {
|
||||
if (!(bot.VALUES_TO_USE.timeFrame === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
@@ -730,19 +639,17 @@
|
||||
let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2);
|
||||
let filePath
|
||||
|
||||
if (dependency.referenceParent.code.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
if (dependency.referenceParent.config.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
} else {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + dateForPath;
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + dateForPath;
|
||||
}
|
||||
let fileName = "Data.json";
|
||||
let fileName = "Data.json";
|
||||
|
||||
datasetModule.getTextFile(filePath, fileName, onFileReceived);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> Entering function."); }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> text = " + text); }
|
||||
|
||||
@@ -776,7 +683,6 @@
|
||||
}
|
||||
|
||||
previousFile = JSON.parse(text);
|
||||
|
||||
getCurrentFile();
|
||||
|
||||
}
|
||||
@@ -796,13 +702,13 @@
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> dependencyLoopBody -> getCurrentFile -> Entering function."); }
|
||||
|
||||
if (dependency.referenceParent.code.codeName !== "Multi-Period-Daily") {
|
||||
if (dependency.referenceParent.config.codeName !== "Multi-Period-Daily") {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
|
||||
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.code.singularVariableName) !== true) {
|
||||
if (!(bot.VALUES_TO_USE.timeFrame === timeFrameLabel && datasetModule.node.parentNode.code.pluralVariableName === 'candles')) {
|
||||
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) {
|
||||
if (!(bot.VALUES_TO_USE.timeFrame === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
|
||||
dependencyControlLoop();
|
||||
return
|
||||
}
|
||||
@@ -810,19 +716,17 @@
|
||||
|
||||
let dateForPath = bot.multiPeriodProcessDatetime.getUTCFullYear() + '/' + utilities.pad(bot.multiPeriodProcessDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.multiPeriodProcessDatetime.getUTCDate(), 2);
|
||||
let filePath
|
||||
if (dependency.referenceParent.code.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
if (dependency.referenceParent.config.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
} else {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + dateForPath;
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + dateForPath;
|
||||
}
|
||||
let fileName = "Data.json";
|
||||
let fileName = "Data.json";
|
||||
|
||||
datasetModule.getTextFile(filePath, fileName, onFileReceived);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> Entering function."); }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> text = " + text); }
|
||||
|
||||
@@ -841,11 +745,8 @@
|
||||
}
|
||||
|
||||
currentFile = JSON.parse(text);
|
||||
|
||||
let dataFile = previousFile.concat(currentFile);
|
||||
|
||||
dataFiles.set(dependency.id, dataFile);
|
||||
|
||||
dependencyControlLoop();
|
||||
|
||||
}
|
||||
@@ -868,24 +769,16 @@
|
||||
}
|
||||
|
||||
function dependencyControlLoop() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> dependencyControlLoop -> Entering function."); }
|
||||
|
||||
dependencyIndex++;
|
||||
|
||||
if (dependencyIndex < dataDependenciesModule.nodeArray.length) {
|
||||
|
||||
dependencyLoopBody();
|
||||
|
||||
} else {
|
||||
|
||||
let mapKey = global.dailyFilePeriods[n][1];
|
||||
multiPeriodDataFiles.set(mapKey, dataFiles)
|
||||
|
||||
timeFramesControlLoop();
|
||||
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
@@ -902,25 +795,17 @@
|
||||
}
|
||||
|
||||
function timeFramesControlLoop() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> timeFramesControlLoop -> Entering function."); }
|
||||
|
||||
n++;
|
||||
|
||||
if (n < global.dailyFilePeriods.length) {
|
||||
|
||||
timeFramesLoopBody();
|
||||
|
||||
} else {
|
||||
|
||||
n = 0;
|
||||
|
||||
if (currentTimeFrame !== undefined) {
|
||||
callTheBot();
|
||||
} else {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> timeFramesControlLoop -> Time Frame not Recognized. Can not continue." );
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> timeFramesControlLoop -> Time Frame not Recognized. Can not continue.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -932,31 +817,26 @@
|
||||
}
|
||||
|
||||
function callTheBot() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> callTheBot -> Entering function."); }
|
||||
|
||||
botInstance.start(
|
||||
multiPeriodDataFiles,
|
||||
currentTimeFrame,
|
||||
currentTimeFrameLabel,
|
||||
bot.multiPeriodProcessDatetime,
|
||||
interExecutionMemoryArray[n],
|
||||
variable,
|
||||
onBotFinished);
|
||||
|
||||
function onBotFinished(err) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> callTheBot -> onBotFinished -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
botNeverRan = false;
|
||||
botNeverRan = false
|
||||
bot.RESUME = true // From here on, all other loops executions must resume from where we left at this current run.
|
||||
|
||||
if (currentTimeFrame > global.dailyFilePeriods[0][0]) {
|
||||
writeMarketStatusReport(onMarketStatusReport)
|
||||
@@ -966,9 +846,7 @@
|
||||
}
|
||||
|
||||
function onWritten(err) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> callTheBot -> onBotFinished -> onWritten -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
@@ -978,7 +856,6 @@
|
||||
}
|
||||
|
||||
writeDailyStatusReport(bot.multiPeriodProcessDatetime, onDailyStatusReport);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> callTheBot -> onBotFinished -> onWritten -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
@@ -991,7 +868,7 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> callTheBot -> onBotFinished -> onDailyStatusReport -> Entering function."); }
|
||||
|
||||
/* The next run we need the process to continue at the date it finished. */
|
||||
processConfig.framework.startDate.resumeExecution = true;
|
||||
processConfig.framework.startDate.resumeExecution = true;
|
||||
|
||||
advanceTime();
|
||||
} catch (err) {
|
||||
@@ -1005,7 +882,6 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> callTheBot -> onBotFinished -> onMarketStatusReport -> Entering function."); }
|
||||
|
||||
/* This is where we check if we need reached the user defined end datetime. */
|
||||
|
||||
const now = new Date()
|
||||
if (now.valueOf() >= bot.VALUES_TO_USE.timeRange.finalDatetime.valueOf()) {
|
||||
|
||||
@@ -1044,23 +920,19 @@
|
||||
}
|
||||
|
||||
function writeDataRanges(currentTimeFrameLabel, callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRanges -> Entering function."); }
|
||||
|
||||
let outputDatasetIndex = -1;
|
||||
controlLoop();
|
||||
|
||||
function productLoopBody() {
|
||||
let productCodeName = bot.processNode.referenceParent.processOutput.outputDatasets[outputDatasetIndex].referenceParent.parentNode.code.codeName;
|
||||
let productCodeName = bot.processNode.referenceParent.processOutput.outputDatasets[outputDatasetIndex].referenceParent.parentNode.config.codeName;
|
||||
writeDataRange(contextVariables.dateBeginOfMarket, bot.multiPeriodProcessDatetime, productCodeName, currentTimeFrameLabel, controlLoop);
|
||||
}
|
||||
|
||||
function controlLoop() {
|
||||
|
||||
outputDatasetIndex++;
|
||||
|
||||
if (outputDatasetIndex < bot.processNode.referenceParent.processOutput.outputDatasets.length) {
|
||||
productLoopBody();
|
||||
} else {
|
||||
@@ -1076,25 +948,20 @@
|
||||
}
|
||||
|
||||
function writeDataRange(pBegin, pEnd, productCodeName, currentTimeFrameLabel, callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> Entering function."); }
|
||||
|
||||
let dataRange = {
|
||||
begin: pBegin.valueOf(),
|
||||
end: pEnd.valueOf() + ONE_DAY_IN_MILISECONDS
|
||||
};
|
||||
|
||||
let fileContent = JSON.stringify(dataRange);
|
||||
|
||||
let fileName = '/Data.Range.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + productCodeName + "/" + 'Multi-Period-Daily' + fileName;
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
|
||||
function onFileCreated(err) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
@@ -1107,11 +974,11 @@
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Content written = " + fileContent);
|
||||
}
|
||||
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + productCodeName + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + productCodeName + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let event = {
|
||||
dateRange: dataRange
|
||||
}
|
||||
|
||||
|
||||
global.EVENT_SERVER_CLIENT.raiseEvent(key, 'Data Range Updated', event)
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
@@ -1124,22 +991,19 @@
|
||||
}
|
||||
|
||||
function writeDailyStatusReport(lastFileDate, callBack) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyStatusReport -> Entering function."); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyStatusReport -> lastFileDate = " + lastFileDate); }
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = bot.dataMine + "-" + bot.codeName + "-" + "Multi-Period" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.currentDaytime;
|
||||
thisReport.file.lastFile = lastFileDate;
|
||||
thisReport.file.interExecutionMemoryArray = interExecutionMemoryArray;
|
||||
thisReport.file.variable = variable;
|
||||
thisReport.save(callBack);
|
||||
|
||||
bot.hasTheBotJustStarted = false;
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyStatusReport -> err = " + err.stack);
|
||||
@@ -1148,15 +1012,13 @@
|
||||
}
|
||||
|
||||
function writeMarketStatusReport(callBack) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketStatusReport -> Entering function."); }
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = bot.dataMine + "-" + bot.codeName + "-" + "Multi-Period" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.processDatetime;
|
||||
thisReport.file.variable = variable;
|
||||
thisReport.save(callBack);
|
||||
|
||||
logger.newInternalLoop(bot.codeName, bot.process, bot.multiPeriodProcessDatetime);
|
||||
@@ -1166,15 +1028,12 @@
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function pad(str, max) {
|
||||
str = str.toString();
|
||||
return str.length < max ? pad(" " + str, max) : str;
|
||||
|
||||
+38
-38
@@ -22,7 +22,7 @@
|
||||
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
let bootstrappingTheProcess = false
|
||||
let bootstrappingTheProcess = false
|
||||
|
||||
let processConfig;
|
||||
let beginingOfMarket
|
||||
@@ -48,7 +48,7 @@
|
||||
botInstance.initialize(callBackFunction);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,7 @@
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> err = " + err.stack);
|
||||
if (err.message === "Cannot read property 'file' of undefined") {
|
||||
logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Check the bot configuration to see if all of its statusDependencies declarations are correct. ");
|
||||
logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys));
|
||||
@@ -280,7 +280,7 @@
|
||||
|
||||
bot.multiPeriodDailyProcessDatetime = new Date(bot.multiPeriodDailyProcessDatetime.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
previousDay = new Date(bot.multiPeriodDailyProcessDatetime.valueOf() - ONE_DAY_IN_MILISECONDS);
|
||||
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> advanceTime -> bot.multiPeriodDailyProcessDatetime = " + bot.multiPeriodDailyProcessDatetime); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> advanceTime -> previousDay = " + previousDay); }
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
let currentDateString = bot.multiPeriodDailyProcessDatetime.getUTCFullYear() + '-' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCMonth() + 1, 2) + '-' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCDate(), 2);
|
||||
let currentDate = new Date(bot.multiPeriodDailyProcessDatetime)
|
||||
let percentage = global.getPercentage(fromDate, currentDate, lastDate)
|
||||
bot.processHeartBeat(currentDateString, percentage)
|
||||
bot.processHeartBeat(currentDateString, percentage)
|
||||
|
||||
if (global.areEqualDates(currentDate, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, currentDate, percentage);
|
||||
@@ -309,7 +309,7 @@
|
||||
checkStopTaskGracefully();
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> advanceTime -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> advanceTime -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -355,7 +355,7 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -395,9 +395,9 @@
|
||||
|
||||
let dependency = dataDependenciesModule.nodeArray[dependencyIndex];
|
||||
|
||||
if (dependency === undefined ) {
|
||||
if (dependency === undefined) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> You need to add at least one Data Dependency to the process Multi Period Daily. Aborting process." );
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> You need to add at least one Data Dependency to the process Multi Period Daily. Aborting process.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
@@ -422,10 +422,10 @@
|
||||
|
||||
let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2);
|
||||
let filePath
|
||||
if (dependency.referenceParent.code.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
if (dependency.referenceParent.config.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
} else {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + dateForPath;
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + dateForPath;
|
||||
}
|
||||
let fileName = "Data.json";
|
||||
|
||||
@@ -455,14 +455,14 @@
|
||||
|
||||
if ((err.result === "Fail Because" && err.message === "File does not exist.") || err.code === 'The specified key does not exist.') {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
@@ -473,13 +473,13 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -492,12 +492,12 @@
|
||||
|
||||
let dateForPath = bot.multiPeriodDailyProcessDatetime.getUTCFullYear() + '/' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCDate(), 2);
|
||||
let filePath
|
||||
if (dependency.referenceParent.code.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
if (dependency.referenceParent.config.codeName === "Multi-Period-Daily") {
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
} else {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + dateForPath;
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + dateForPath;
|
||||
}
|
||||
let fileName = "Data.json";
|
||||
let fileName = "Data.json";
|
||||
|
||||
datasetModule.getTextFile(filePath, fileName, onFileReceived);
|
||||
|
||||
@@ -543,19 +543,19 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> Catch Error -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> Catch Error -> onFileReceived -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> dependencyLoopBody -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> dependencyLoopBody -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -579,7 +579,7 @@
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> dependencyControlLoop -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> dependencyControlLoop -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -617,19 +617,19 @@
|
||||
periodsControlLoop();
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -659,7 +659,7 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> controlLoop -> onWritten -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> controlLoop -> onWritten -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> controlLoop -> onWritten -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
@@ -667,21 +667,21 @@
|
||||
writeStatusReport(bot.multiPeriodDailyProcessDatetime, advanceTime);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> controlLoop -> onWritten -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> controlLoop -> onWritten -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsControlLoop -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsControlLoop -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -696,7 +696,7 @@
|
||||
controlLoop();
|
||||
|
||||
function productLoopBody() {
|
||||
let productCodeName = bot.processNode.referenceParent.processOutput.outputDatasets[outputDatasetIndex].referenceParent.parentNode.code.codeName;
|
||||
let productCodeName = bot.processNode.referenceParent.processOutput.outputDatasets[outputDatasetIndex].referenceParent.parentNode.config.codeName;
|
||||
writeDataRange(contextVariables.dateBeginOfMarket, bot.multiPeriodDailyProcessDatetime, productCodeName, controlLoop);
|
||||
}
|
||||
|
||||
@@ -712,7 +712,7 @@
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDataRanges -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDataRanges -> err = " + err.stack);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
|
||||
@@ -741,7 +741,7 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> onFileCreated -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> onFileCreated -> err = " + err.stack);
|
||||
callBack(err);
|
||||
return;
|
||||
}
|
||||
@@ -750,7 +750,7 @@
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Content written = " + fileContent);
|
||||
}
|
||||
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + productCodeName + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + productCodeName + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let event = {
|
||||
dateRange: dataRange
|
||||
}
|
||||
@@ -761,7 +761,7 @@
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> err = " + err.stack);
|
||||
callBack(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -786,14 +786,14 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-22
@@ -41,7 +41,7 @@
|
||||
botInstance.initialize(callBackFunction);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -137,13 +137,13 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getFile -> Entering function."); }
|
||||
|
||||
let dateForPath = bot.processDatetime.getUTCFullYear() + '/' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.processDatetime.getUTCDate(), 2);
|
||||
let fileName = "Data.json";
|
||||
let fileName = "Data.json";
|
||||
|
||||
let filePath
|
||||
if (dependency.referenceParent.code.codeName === "Multi-Period-Market") {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + timeFrameLabel;
|
||||
if (dependency.referenceParent.config.codeName === "Multi-Period-Market") {
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel;
|
||||
} else {
|
||||
filePath = dependency.referenceParent.parentNode.code.codeName + '/' + dependency.referenceParent.code.codeName + "/" + dateForPath;
|
||||
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + dateForPath;
|
||||
}
|
||||
datasetModule.getTextFile(filePath, fileName, onFileReceived);
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
@@ -168,20 +168,20 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getFile -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> dependencyLoopBody -> getFile -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> dependencyLoopBody -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoop -> dependencyLoopBody -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> dependencyControlLoop -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> dependencyControlLoop -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -242,19 +242,19 @@
|
||||
periodsControlLoop();
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(err){
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> err = "+ err.stack);
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -278,14 +278,14 @@
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsControlLoop -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsControlLoop -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -304,23 +304,23 @@
|
||||
|
||||
if (global.areEqualDates(bot.processDatetime, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, bot.processDatetime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let currentDateString = bot.processDatetime.getUTCFullYear() + '-' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '-' + utilities.pad(bot.processDatetime.getUTCDate(), 2);
|
||||
let currentDate = new Date(bot.processDatetime)
|
||||
let lastDate = new Date()
|
||||
bot.processHeartBeat(currentDateString, global.getPercentage(currentDate, currentDate, lastDate))
|
||||
bot.processHeartBeat(currentDateString, global.getPercentage(currentDate, currentDate, lastDate))
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
const MODULE_NAME = "Process Execution Events";
|
||||
logger.fileName = MODULE_NAME
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let bot = BOT;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
let market = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let market = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
currentProcessKey = bot.processNode.referenceParent.name + "-" + bot.processNode.referenceParent.type + "-" + bot.processNode.referenceParent.id + "-" + bot.exchange + "-" + market
|
||||
|
||||
if (bot.processNode.referenceParent.executionStartedEvent !== undefined) {
|
||||
@@ -52,7 +52,7 @@
|
||||
processThisDependsOn = bot.processNode.referenceParent.executionStartedEvent.referenceParent.parentNode
|
||||
|
||||
name = processThisDependsOn.name
|
||||
if (processThisDependsOn.code.monthlyInstances === true) {
|
||||
if (processThisDependsOn.config.monthlyInstances === true) {
|
||||
logger.fileName = MODULE_NAME + "." + name;
|
||||
}
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> " + currentProcessKey + " depends on " + name); }
|
||||
@@ -90,13 +90,13 @@
|
||||
/* We found where the task that runs the process definition we are waiting for is located on the network. */
|
||||
|
||||
thisObject.networkNode = networkNode
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Connecting to Websockets Server " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webSocketsPort + '.'); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Connecting to Websockets Server " + networkNode.name + " -> host = " + networkNode.config.host + ' -> port = ' + networkNode.config.webSocketsPort + '.'); }
|
||||
|
||||
eventServerClient = EVENT_SERVER_CLIENT.newEventsServerClient(networkNode.code.host, networkNode.code.webSocketsPort)
|
||||
eventServerClient = EVENT_SERVER_CLIENT.newEventsServerClient(networkNode.config.host, networkNode.config.webSocketsPort)
|
||||
eventServerClient.initialize(onConnected)
|
||||
|
||||
function onConnected() {
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Connected to Websockets Server " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webSocketsPort + '.'); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Connected to Websockets Server " + networkNode.name + " -> host = " + networkNode.config.host + ' -> port = ' + networkNode.config.webSocketsPort + '.'); }
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return
|
||||
@@ -119,7 +119,7 @@
|
||||
return
|
||||
}
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
@@ -151,7 +151,7 @@
|
||||
|
||||
let extraCallerId = '-' + Math.trunc(Math.random() * 10000) + '-'
|
||||
|
||||
let market = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let market = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let key = processThisDependsOn.name + "-" + processThisDependsOn.type + "-" + processThisDependsOn.id + "-" + bot.exchange + "-" + market
|
||||
let callerId = bot.dataMine + "-" + bot.codeName + "-" + bot.process + extraCallerId
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
eventServerClient.listenToEvent(key, 'Process Execution Finished', undefined, callerId, responseCallBack, eventsCallBack)
|
||||
|
||||
bot.processHeartBeat(undefined, undefined, "Waiting for " + thisObject.networkNode.name + "->" + processThisDependsOn.parentNode.parentNode.name + "->" + processThisDependsOn.parentNode.code.codeName + "->" + processThisDependsOn.code.codeName)
|
||||
bot.processHeartBeat(undefined, undefined, "Waiting for " + thisObject.networkNode.name + "->" + processThisDependsOn.parentNode.parentNode.name + "->" + processThisDependsOn.parentNode.config.codeName + "->" + processThisDependsOn.config.codeName)
|
||||
|
||||
function responseCallBack(message) {
|
||||
if (message.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
@@ -192,9 +192,9 @@
|
||||
global.EVENT_SERVER_CLIENT.createEventHandler(currentProcessKey, 'Process Execution Started')
|
||||
global.EVENT_SERVER_CLIENT.raiseEvent(currentProcessKey, 'Process Execution Started', event)
|
||||
|
||||
bot.processHeartBeat(undefined, undefined,"Running...")
|
||||
bot.processHeartBeat(undefined, undefined, "Running...")
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> " + currentProcessKey + " Process Execution Started because " + key + " Finished."); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> " + currentProcessKey + " Process Execution Started because " + key + " Finished."); }
|
||||
}
|
||||
|
||||
callBackFunction(message.event.err);
|
||||
@@ -208,7 +208,7 @@
|
||||
global.EVENT_SERVER_CLIENT.createEventHandler(currentProcessKey, 'Process Execution Started')
|
||||
global.EVENT_SERVER_CLIENT.raiseEvent(currentProcessKey, 'Process Execution Started', event)
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> " + currentProcessKey + " Process Execution Started " ); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> " + currentProcessKey + " Process Execution Started "); }
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
}
|
||||
@@ -232,7 +232,7 @@
|
||||
global.EVENT_SERVER_CLIENT.createEventHandler(currentProcessKey, 'Process Execution Finished')
|
||||
global.EVENT_SERVER_CLIENT.raiseEvent(currentProcessKey, 'Process Execution Finished', event)
|
||||
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] finish -> " + currentProcessKey + " Process Execution Finished " ); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] finish -> " + currentProcessKey + " Process Execution Finished "); }
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
|
||||
+12
-12
@@ -30,29 +30,29 @@
|
||||
|
||||
/* Some validations to verify that everything is in place. */
|
||||
if (outputDataset.referenceParent !== undefined) {
|
||||
if (outputDataset.referenceParent.code.codeName === undefined) {
|
||||
if (outputDataset.referenceParent.config.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) {
|
||||
if (outputDataset.referenceParent.parentNode.config.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) {
|
||||
if (outputDataset.referenceParent.parentNode.parentNode.config.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) {
|
||||
if (outputDataset.referenceParent.parentNode.parentNode.parentNode.config.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> codeName at Data Mine not defined. Data Mine = " + 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 Data Mine. Bot = " + JSON.stringify(outputDataset.referenceParent.parentNode.parentNode));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
@@ -76,10 +76,10 @@
|
||||
|
||||
/* All good, lets emit the event. */
|
||||
|
||||
let dataMine = 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 dataMine = outputDataset.referenceParent.parentNode.parentNode.parentNode.config.codeName
|
||||
let botName = outputDataset.referenceParent.parentNode.parentNode.config.codeName
|
||||
let product = outputDataset.referenceParent.parentNode.config.codeName
|
||||
let dataset = outputDataset.referenceParent.config.codeName
|
||||
|
||||
key = dataMine + "-" + botName + "-" + product + "-" + dataset + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let event = {
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
console.log(logDisplace + "Root : [ERROR] initialize -> err = " + err.stack);
|
||||
console.log(logDisplace + "Root : [ERROR] initialize -> err = " + err.stack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -141,19 +141,19 @@
|
||||
|
||||
/* 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
|
||||
processInstance.referenceParent.config.framework !== undefined &&
|
||||
(processInstance.referenceParent.config.framework.name === 'Multi-Period-Market' ||
|
||||
processInstance.referenceParent.config.framework.name === 'Multi-Period-Daily' ||
|
||||
processInstance.referenceParent.config.framework.name === 'Multi-Period')
|
||||
) {
|
||||
botConfig = processInstance.referenceParent.parentNode.config
|
||||
botConfig.definedByUI = true
|
||||
bootingBot(processIndex)
|
||||
return
|
||||
} else {
|
||||
getBotConfigFromFile();
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function getBotConfigFromFile() {
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
const FILE_STORAGE = require('./FileStorage.js');
|
||||
let fileStorage = FILE_STORAGE.newFileStorage();
|
||||
|
||||
let filePath = global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName + '/bots/' + global.TASK_NODE.bot.code.repo + '/this.bot.config.json';
|
||||
let filePath = global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName + '/bots/' + global.TASK_NODE.bot.config.repo + '/this.bot.config.json';
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
|
||||
@@ -171,13 +171,13 @@
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
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 -> dataMine = " + global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName);
|
||||
console.log(logDisplace + "Root : [ERROR] start -> getBotConfigFromFile -> onInizialized -> onFileReceived -> dataMine = " + global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
botConfig = JSON.parse(text);
|
||||
botConfig.repo = global.TASK_NODE.bot.code.repo;
|
||||
botConfig.repo = global.TASK_NODE.bot.config.repo;
|
||||
bootingBot(processIndex);
|
||||
} catch (err) {
|
||||
console.log(logDisplace + "Root : [ERROR] start -> getBotConfigFromFile -> onInizialized -> onFileReceived -> err = " + JSON.stringify(err));
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
try {
|
||||
|
||||
botConfig.process = global.TASK_NODE.bot.processes[processIndex].referenceParent.code.codeName
|
||||
botConfig.process = global.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName
|
||||
botConfig.debug = {};
|
||||
botConfig.processNode = global.TASK_NODE.bot.processes[processIndex]
|
||||
|
||||
@@ -204,15 +204,15 @@
|
||||
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.
|
||||
|
||||
/* Simplifying the access to basic info */
|
||||
botConfig.dataMine = global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName
|
||||
botConfig.dataMine = global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName
|
||||
botConfig.exchange = global.TASK_NODE.bot.processes[processIndex].marketReference.referenceParent.parentNode.parentNode.name
|
||||
botConfig.exchangeNode = global.TASK_NODE.bot.processes[processIndex].marketReference.referenceParent.parentNode.parentNode
|
||||
botConfig.market = {
|
||||
baseAsset: global.TASK_NODE.bot.processes[processIndex].marketReference.referenceParent.baseAsset.referenceParent.code.codeName,
|
||||
quotedAsset: global.TASK_NODE.bot.processes[processIndex].marketReference.referenceParent.quotedAsset.referenceParent.code.codeName
|
||||
baseAsset: global.TASK_NODE.bot.processes[processIndex].marketReference.referenceParent.baseAsset.referenceParent.config.codeName,
|
||||
quotedAsset: global.TASK_NODE.bot.processes[processIndex].marketReference.referenceParent.quotedAsset.referenceParent.config.codeName
|
||||
}
|
||||
botConfig.uiStartDate = global.TASK_NODE.bot.code.startDate
|
||||
botConfig.code = global.TASK_NODE.bot.code
|
||||
botConfig.uiStartDate = global.TASK_NODE.bot.config.startDate
|
||||
botConfig.config = global.TASK_NODE.bot.config
|
||||
|
||||
/* This stuff is still hardcoded and unresolved. */
|
||||
botConfig.version = {
|
||||
@@ -222,10 +222,10 @@
|
||||
botConfig.dataSetVersion = "dataSet.V1"
|
||||
|
||||
/* Loop Counter */
|
||||
botConfig.loopCounter = 0;
|
||||
botConfig.loopCounter = 0;
|
||||
|
||||
/* File Path Root */
|
||||
botConfig.filePathRoot = botConfig.exchange + "/" + botConfig.market.baseAsset + "-" + botConfig.market.quotedAsset + "/" + botConfig.dataMine + "/" + botConfig.codeName ;
|
||||
botConfig.filePathRoot = botConfig.exchange + "/" + botConfig.market.baseAsset + "-" + botConfig.market.quotedAsset + "/" + botConfig.dataMine + "/" + botConfig.codeName;
|
||||
|
||||
/* 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
|
||||
@@ -243,14 +243,14 @@
|
||||
if (botConfig.processNode.marketReference.keyInstance.referenceParent !== undefined) {
|
||||
let key = botConfig.processNode.marketReference.keyInstance.referenceParent
|
||||
|
||||
process.env.KEY = key.code.codeName
|
||||
process.env.SECRET = key.code.secret
|
||||
process.env.KEY = key.config.codeName
|
||||
process.env.SECRET = key.config.secret
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let processConfig = global.TASK_NODE.bot.processes[processIndex].referenceParent.code
|
||||
let processConfig = global.TASK_NODE.bot.processes[processIndex].referenceParent.config
|
||||
|
||||
if (processConfig.framework !== undefined) {
|
||||
if (processConfig.framework.name === "Multi-Period-Daily" || processConfig.framework.name === "Multi-Period-Market" || processConfig.framework.name === "Multi-Period") {
|
||||
@@ -283,7 +283,7 @@
|
||||
if (processConfig.startMode === undefined) { // Default
|
||||
|
||||
botConfig.hasTheBotJustStarted = true;
|
||||
|
||||
|
||||
switch (botConfig.type) {
|
||||
case 'Sensor Bot': {
|
||||
runSensorBot(botConfig, processConfig);
|
||||
@@ -475,7 +475,7 @@
|
||||
pBotConfig.loopCounter = 0;
|
||||
|
||||
let botId = pBotConfig.dataMine + "." + pBotConfig.codeName + "." + pBotConfig.process;
|
||||
|
||||
|
||||
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
|
||||
|
||||
+89
-78
@@ -5,7 +5,7 @@
|
||||
const ONE_YEAR_IN_MILISECONDS = 365 * 24 * 60 * 60 * 1000
|
||||
|
||||
let thisObject = {
|
||||
initialize: initialize
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
return thisObject;
|
||||
@@ -17,19 +17,19 @@
|
||||
let telegramAPI
|
||||
|
||||
/* Initialize this info so that everything is logged propeerly */
|
||||
|
||||
|
||||
bot.SESSION = {
|
||||
name: bot.processNode.session.name,
|
||||
id: bot.processNode.session.id
|
||||
id: bot.processNode.session.id
|
||||
}
|
||||
|
||||
/* Set the folderName for early logging */
|
||||
if (bot.processNode.session.code.folderName === undefined) {
|
||||
if (bot.processNode.session.config.folderName === undefined) {
|
||||
bot.SESSION.folderName = bot.SESSION.id
|
||||
} else {
|
||||
bot.SESSION.folderName = bot.processNode.session.code.folderName + "-" + bot.SESSION.id
|
||||
bot.SESSION.folderName = bot.processNode.session.config.folderName + "-" + bot.SESSION.id
|
||||
}
|
||||
|
||||
|
||||
/* Check if there is a session */
|
||||
if (bot.processNode.session === undefined) {
|
||||
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> Cannot run without a Session.");
|
||||
@@ -40,7 +40,7 @@
|
||||
/* Listen to event to start or stop the session. */
|
||||
bot.sessionKey = bot.processNode.session.name + '-' + bot.processNode.session.type + '-' + bot.processNode.session.id
|
||||
global.SESSION_MAP.set(bot.sessionKey, bot.sessionKey)
|
||||
|
||||
|
||||
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Run Session', undefined, bot.sessionKey, undefined, runSession)
|
||||
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Stop Session', undefined, bot.sessionKey, undefined, stopSession)
|
||||
|
||||
@@ -53,18 +53,29 @@
|
||||
if (bot.SESSION_STATUS === 'Idle' || bot.SESSION_STATUS === 'Running') { return } // This happens when the UI is reloaded, the session was running and tries to run it again.
|
||||
|
||||
/* We are going to run the Definition comming at the event. */
|
||||
bot.APP_SCHEMA_ARRAY = JSON.parse(message.event.appSchema)
|
||||
bot.TRADING_SYSTEM = JSON.parse(message.event.tradingSystem)
|
||||
bot.TRADING_ENGINE = JSON.parse(message.event.tradingEngine)
|
||||
bot.SESSION = JSON.parse(message.event.session)
|
||||
bot.DEPENDENCY_FILTER = JSON.parse(message.event.dependencyFilter)
|
||||
bot.RESUME = message.event.resume
|
||||
|
||||
/* Setup the APP_SCHEMA_MAP based on the APP_SCHEMA_ARRAY */
|
||||
bot.APP_SCHEMA_MAP = new Map()
|
||||
for (let i = 0; i < bot.APP_SCHEMA_ARRAY.length; i++) {
|
||||
let nodeDefinition = bot.APP_SCHEMA_ARRAY[i]
|
||||
let key = nodeDefinition.type
|
||||
bot.APP_SCHEMA_MAP.set(key, nodeDefinition)
|
||||
}
|
||||
|
||||
/* Set the folderName for logging, reports, context and data output */
|
||||
let code
|
||||
if (bot.SESSION.code !== undefined) {
|
||||
code = bot.SESSION.code
|
||||
if (code.folderName === undefined) {
|
||||
let config
|
||||
if (bot.SESSION.config !== undefined) {
|
||||
config = bot.SESSION.config
|
||||
if (config.folderName === undefined) {
|
||||
bot.SESSION.folderName = bot.SESSION.id
|
||||
} else {
|
||||
bot.SESSION.folderName = code.folderName + "-" + bot.SESSION.id
|
||||
bot.SESSION.folderName = config.folderName + "-" + bot.SESSION.id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +144,7 @@
|
||||
}
|
||||
bot.resumeExecution = false;
|
||||
bot.hasTheBotJustStarted = true
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -148,7 +159,7 @@
|
||||
bot.startMode = "Live"
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.hasTheBotJustStarted = true
|
||||
pProcessConfig.liveWaitTime = getTimeFrameFromLabel(bot.VALUES_TO_USE.timeFrame)
|
||||
return true
|
||||
@@ -165,23 +176,23 @@
|
||||
bot.startMode = "Live"
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.hasTheBotJustStarted = true
|
||||
|
||||
/* Reduce the balance */
|
||||
|
||||
let balancePercentage = 1 // This is the default value
|
||||
|
||||
if (bot.SESSION.code.balancePercentage !== undefined) {
|
||||
balancePercentage = bot.SESSION.code.balancePercentage
|
||||
|
||||
if (bot.SESSION.config.balancePercentage !== undefined) {
|
||||
balancePercentage = bot.SESSION.config.balancePercentage
|
||||
}
|
||||
|
||||
bot.VALUES_TO_USE.initialBalanceA = bot.VALUES_TO_USE.initialBalanceA * balancePercentage / 100
|
||||
bot.VALUES_TO_USE.initialBalanceB = bot.VALUES_TO_USE.initialBalanceB * balancePercentage / 100
|
||||
|
||||
|
||||
bot.VALUES_TO_USE.minimumBalanceA = bot.VALUES_TO_USE.minimumBalanceA * balancePercentage / 100
|
||||
bot.VALUES_TO_USE.minimumBalanceB = bot.VALUES_TO_USE.minimumBalanceB * balancePercentage / 100
|
||||
|
||||
|
||||
bot.VALUES_TO_USE.maximumBalanceA = bot.VALUES_TO_USE.maximumBalanceA * balancePercentage / 100
|
||||
bot.VALUES_TO_USE.maximumBalanceB = bot.VALUES_TO_USE.maximumBalanceB * balancePercentage / 100
|
||||
|
||||
@@ -192,11 +203,11 @@
|
||||
|
||||
function startPaperTrading(message) {
|
||||
bot.startMode = "Backtest"
|
||||
|
||||
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.hasTheBotJustStarted = true
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
pProcessConfig.normalWaitTime = getTimeFrameFromLabel(bot.VALUES_TO_USE.timeFrame)
|
||||
return true
|
||||
}
|
||||
@@ -270,7 +281,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
let tradingSystem = bot.TRADING_SYSTEM
|
||||
let tradingSystem = bot.TRADING_SYSTEM
|
||||
|
||||
if (tradingSystem !== undefined) {
|
||||
|
||||
@@ -284,38 +295,38 @@
|
||||
if (bot.SESSION.parameters.baseAsset.referenceParent !== undefined) {
|
||||
if (bot.SESSION.parameters.baseAsset.referenceParent.referenceParent !== undefined) {
|
||||
|
||||
let code = bot.SESSION.parameters.baseAsset.referenceParent.referenceParent.code
|
||||
let config = bot.SESSION.parameters.baseAsset.referenceParent.referenceParent.config
|
||||
|
||||
if (code.codeName !== undefined) {
|
||||
bot.VALUES_TO_USE.baseAsset = code.codeName;
|
||||
if (config.codeName !== undefined) {
|
||||
bot.VALUES_TO_USE.baseAsset = config.codeName;
|
||||
}
|
||||
|
||||
code = bot.SESSION.parameters.baseAsset.code
|
||||
config = bot.SESSION.parameters.baseAsset.config
|
||||
|
||||
if (bot.VALUES_TO_USE.baseAsset === bot.market.baseAsset) {
|
||||
if (code.initialBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.initialBalanceA = code.initialBalance;
|
||||
if (config.initialBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.initialBalanceA = config.initialBalance;
|
||||
bot.VALUES_TO_USE.initialBalanceB = 0
|
||||
}
|
||||
if (code.minimumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.minimumBalanceA = code.minimumBalance;
|
||||
if (config.minimumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.minimumBalanceA = config.minimumBalance;
|
||||
bot.VALUES_TO_USE.minimumBalanceB = 0
|
||||
}
|
||||
if (code.maximumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.maximumBalanceA = code.maximumBalance;
|
||||
if (config.maximumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.maximumBalanceA = config.maximumBalance;
|
||||
bot.VALUES_TO_USE.maximumBalanceB = 0
|
||||
}
|
||||
} else {
|
||||
if (code.initialBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.initialBalanceB = code.initialBalance;
|
||||
if (config.initialBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.initialBalanceB = config.initialBalance;
|
||||
bot.VALUES_TO_USE.initialBalanceA = 0
|
||||
}
|
||||
if (code.minimumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.minimumBalanceB = code.minimumBalance;
|
||||
if (config.minimumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.minimumBalanceB = config.minimumBalance;
|
||||
bot.VALUES_TO_USE.minimumBalanceA = 0
|
||||
}
|
||||
if (code.maximumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.maximumBalanceB = code.maximumBalance;
|
||||
if (config.maximumBalance !== undefined) {
|
||||
bot.VALUES_TO_USE.maximumBalanceB = config.maximumBalance;
|
||||
bot.VALUES_TO_USE.maximumBalanceA = 0
|
||||
}
|
||||
}
|
||||
@@ -347,10 +358,10 @@
|
||||
if (bot.SESSION.parameters.quotedAsset.referenceParent !== undefined) {
|
||||
if (bot.SESSION.parameters.quotedAsset.referenceParent.referenceParent !== undefined) {
|
||||
|
||||
let code = bot.SESSION.parameters.quotedAsset.referenceParent.referenceParent.code
|
||||
let config = bot.SESSION.parameters.quotedAsset.referenceParent.referenceParent.config
|
||||
|
||||
if (code.codeName !== undefined) {
|
||||
bot.VALUES_TO_USE.quotedAsset = code.codeName;
|
||||
if (config.codeName !== undefined) {
|
||||
bot.VALUES_TO_USE.quotedAsset = config.codeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,59 +370,59 @@
|
||||
|
||||
/* Time Frame */
|
||||
if (bot.SESSION.parameters.timeFrame !== undefined) {
|
||||
bot.VALUES_TO_USE.timeFrame = bot.SESSION.parameters.timeFrame.code.value
|
||||
bot.VALUES_TO_USE.timeFrame = bot.SESSION.parameters.timeFrame.config.value
|
||||
}
|
||||
|
||||
/* Slippage */
|
||||
if (bot.SESSION.parameters.slippage !== undefined) {
|
||||
if (bot.SESSION.parameters.slippage.code !== undefined) {
|
||||
if (bot.SESSION.parameters.slippage.config !== undefined) {
|
||||
|
||||
let code = bot.SESSION.parameters.slippage.code
|
||||
let config = bot.SESSION.parameters.slippage.config
|
||||
|
||||
if (code.positionRate !== undefined) {
|
||||
bot.VALUES_TO_USE.slippage.positionRate = code.positionRate
|
||||
if (config.positionRate !== undefined) {
|
||||
bot.VALUES_TO_USE.slippage.positionRate = config.positionRate
|
||||
}
|
||||
if (code.stopLoss !== undefined) {
|
||||
bot.VALUES_TO_USE.slippage.stopLoss = code.stopLoss
|
||||
if (config.stopLoss !== undefined) {
|
||||
bot.VALUES_TO_USE.slippage.stopLoss = config.stopLoss
|
||||
}
|
||||
if (code.takeProfit !== undefined) {
|
||||
bot.VALUES_TO_USE.slippage.takeProfit = code.takeProfit
|
||||
if (config.takeProfit !== undefined) {
|
||||
bot.VALUES_TO_USE.slippage.takeProfit = config.takeProfit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fee Structure */
|
||||
if (bot.SESSION.parameters.feeStructure !== undefined) {
|
||||
if (bot.SESSION.parameters.feeStructure.code !== undefined) {
|
||||
if (bot.SESSION.parameters.feeStructure.config !== undefined) {
|
||||
|
||||
let code = bot.SESSION.parameters.feeStructure.code
|
||||
let config = bot.SESSION.parameters.feeStructure.config
|
||||
|
||||
if (code.maker !== undefined) {
|
||||
bot.VALUES_TO_USE.feeStructure.maker = code.maker
|
||||
if (config.maker !== undefined) {
|
||||
bot.VALUES_TO_USE.feeStructure.maker = config.maker
|
||||
}
|
||||
if (code.taker !== undefined) {
|
||||
bot.VALUES_TO_USE.feeStructure.taker = code.taker
|
||||
if (config.taker !== undefined) {
|
||||
bot.VALUES_TO_USE.feeStructure.taker = config.taker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Time Range */
|
||||
if (bot.SESSION.parameters.timeRange !== undefined) {
|
||||
if (bot.SESSION.parameters.timeRange.code !== undefined) {
|
||||
if (bot.SESSION.parameters.timeRange.config !== undefined) {
|
||||
|
||||
let code = bot.SESSION.parameters.timeRange.code
|
||||
if (code.initialDatetime !== undefined) {
|
||||
if (isNaN(Date.parse(code.initialDatetime)) === true) {
|
||||
let config = bot.SESSION.parameters.timeRange.config
|
||||
if (config.initialDatetime !== undefined) {
|
||||
if (isNaN(Date.parse(config.initialDatetime)) === true) {
|
||||
parentLogger.write(MODULE_NAME, "[WARN] initialize -> runSession -> setValuesToUse -> Cannot use initialDatatime provided at Session Parameters because it is not a valid Date.");
|
||||
} else {
|
||||
bot.VALUES_TO_USE.timeRange.initialDatetime = new Date(code.initialDatetime)
|
||||
bot.VALUES_TO_USE.timeRange.initialDatetime = new Date(config.initialDatetime)
|
||||
}
|
||||
}
|
||||
if (code.finalDatetime !== undefined) {
|
||||
if (isNaN(Date.parse(code.finalDatetime)) === true) {
|
||||
if (config.finalDatetime !== undefined) {
|
||||
if (isNaN(Date.parse(config.finalDatetime)) === true) {
|
||||
parentLogger.write(MODULE_NAME, "[WARN] initialize -> runSession -> setValuesToUse -> Cannot use finalDatetime provided at Session Parameters because it is not a valid Date.");
|
||||
} else {
|
||||
bot.VALUES_TO_USE.timeRange.finalDatetime = new Date(code.finalDatetime)
|
||||
bot.VALUES_TO_USE.timeRange.finalDatetime = new Date(config.finalDatetime)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -428,8 +439,8 @@
|
||||
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
|
||||
let socialBot = bot.SESSION.socialBots.bots[i]
|
||||
if (socialBot.type === "Telegram Bot") {
|
||||
let code = socialBot.code
|
||||
socialBot.botInstance = initializeTelegramBot(code.botToken, code.chatId)
|
||||
let config = socialBot.config
|
||||
socialBot.botInstance = initializeTelegramBot(config.botToken, config.chatId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -439,16 +450,16 @@
|
||||
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
|
||||
let socialBot = bot.SESSION.socialBots.bots[i]
|
||||
try {
|
||||
let code = announcement.code
|
||||
|
||||
let config = announcement.config
|
||||
|
||||
if (socialBot.type === "Telegram Bot") {
|
||||
if (announcement.formulaValue !== undefined) {
|
||||
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, announcement.formulaValue).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err))
|
||||
} else {
|
||||
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, code.text).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err))
|
||||
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, config.text).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (err) {
|
||||
parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> err = " + err.stack);
|
||||
}
|
||||
@@ -461,13 +472,13 @@
|
||||
}
|
||||
|
||||
function finalizeSocialBots() {
|
||||
if (bot.SESSION.socialBots === undefined) {return}
|
||||
if (bot.SESSION.socialBots === undefined) { return }
|
||||
if (bot.SESSION.socialBots.bots !== undefined) {
|
||||
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
|
||||
let socialBot = bot.SESSION.socialBots.bots[i]
|
||||
if (socialBot.type === "Telegram Bot") {
|
||||
let code = socialBot.code
|
||||
socialBot.botInstance = finalizeTelegramBot(code.chatId)
|
||||
let config = socialBot.config
|
||||
socialBot.botInstance = finalizeTelegramBot(config.chatId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -488,8 +499,8 @@
|
||||
|
||||
telegramAPI = new Telegram(botToken)
|
||||
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was started with an initial balance of " + " " + bot.VALUES_TO_USE.initialBalanceA + " " + bot.VALUES_TO_USE.baseAsset + "."
|
||||
telegramAPI.sendMessage(chatId, messge ).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err))
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was started with an initial balance of " + " " + bot.VALUES_TO_USE.initialBalanceA + " " + bot.VALUES_TO_USE.baseAsset + "."
|
||||
telegramAPI.sendMessage(chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err))
|
||||
|
||||
let botInstance = {
|
||||
telegramBot: telegramBot,
|
||||
@@ -504,10 +515,10 @@
|
||||
}
|
||||
|
||||
function finalizeTelegramBot(chatId) {
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was stopped."
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was stopped."
|
||||
telegramAPI.sendMessage(chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err))
|
||||
}
|
||||
|
||||
|
||||
} catch (err) {
|
||||
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
|
||||
+25
-25
@@ -23,7 +23,7 @@
|
||||
status: undefined
|
||||
};
|
||||
|
||||
let statusDependencyNode;
|
||||
let statusDependencyNode;
|
||||
|
||||
/* Utilities needed. */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
/* Storage account to be used here. */
|
||||
|
||||
const FILE_STORAGE = require('./FileStorage.js');
|
||||
let fileStorage
|
||||
let fileStorage
|
||||
|
||||
let sessionPath = ''
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
if (statusDependencyNode.referenceParent.parentNode.code.codeName === undefined) {
|
||||
if (statusDependencyNode.referenceParent.parentNode.config.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
|
||||
@@ -71,7 +71,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
if (statusDependencyNode.referenceParent.parentNode.parentNode.code.codeName === undefined) {
|
||||
if (statusDependencyNode.referenceParent.parentNode.parentNode.config.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
|
||||
@@ -83,22 +83,22 @@
|
||||
return
|
||||
}
|
||||
|
||||
if (statusDependencyNode.referenceParent.parentNode.parentNode.parentNode.code.codeName === undefined) {
|
||||
if (statusDependencyNode.referenceParent.parentNode.parentNode.parentNode.config.codeName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> Data Mine witn no codeName defined. Data Mine = " + 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.bot = statusDependencyNode.referenceParent.parentNode.parentNode.config.codeName
|
||||
statusDependencyNode.process = statusDependencyNode.referenceParent.parentNode.config.codeName
|
||||
statusDependencyNode.bottype = statusDependencyNode.referenceParent.parentNode.parentNode.type
|
||||
statusDependencyNode.dataMine = statusDependencyNode.referenceParent.parentNode.parentNode.parentNode.code.codeName
|
||||
statusDependencyNode.dataMine = statusDependencyNode.referenceParent.parentNode.parentNode.parentNode.config.codeName
|
||||
|
||||
/* We retrieve the report main utility */
|
||||
if (statusDependencyNode.code !== undefined) {
|
||||
if (statusDependencyNode.code.mainUtility !== undefined) {
|
||||
thisObject.mainUtility = statusDependencyNode.code.mainUtility
|
||||
if (statusDependencyNode.config !== undefined) {
|
||||
if (statusDependencyNode.config.mainUtility !== undefined) {
|
||||
thisObject.mainUtility = statusDependencyNode.config.mainUtility
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,13 +119,13 @@
|
||||
|
||||
for (let i = 0; i < network.networkNodes.length; i++) {
|
||||
let networkNode = network.networkNodes[i]
|
||||
|
||||
|
||||
if (checkThisBranch(networkNode.dataMining) === true) { return }
|
||||
if (checkThisBranch(networkNode.testingEnvironment) === true) {return}
|
||||
if (checkThisBranch(networkNode.testingEnvironment) === true) { return }
|
||||
if (checkThisBranch(networkNode.productionEnvironment) === true) { return }
|
||||
|
||||
function checkThisBranch(branch) {
|
||||
if (branch === undefined) {return}
|
||||
if (branch === undefined) { return }
|
||||
for (let j = 0; j < branch.exchangeTasks.length; j++) {
|
||||
let exchangeTasks = branch.exchangeTasks[j]
|
||||
for (let k = 0; k < exchangeTasks.taskManagers.length; k++) {
|
||||
@@ -156,9 +156,9 @@
|
||||
/* We found where the task that runs the process definition this status report depends on and where it is located on the network. */
|
||||
|
||||
thisObject.networkNode = networkNode
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving status report from " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webPort + '.'); }
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving status report from " + networkNode.name + " -> host = " + networkNode.config.host + ' -> port = ' + networkNode.config.webPort + '.'); }
|
||||
|
||||
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.code.host, networkNode.code.webPort);
|
||||
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.config.host, networkNode.config.webPort);
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return true
|
||||
}
|
||||
@@ -183,7 +183,7 @@
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -211,9 +211,9 @@
|
||||
|
||||
let rootPath = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + statusDependencyNode.dataMine + "/" + statusDependencyNode.bot
|
||||
|
||||
filePath = rootPath + "/Reports/" + sessionPath + statusDependencyNode.process ;
|
||||
filePath = rootPath + "/Reports/" + sessionPath + statusDependencyNode.process;
|
||||
} else {
|
||||
filePath = bot.filePathRoot + "/Reports/" + sessionPath + statusDependencyNode.process ;
|
||||
filePath = bot.filePathRoot + "/Reports/" + sessionPath + statusDependencyNode.process;
|
||||
}
|
||||
|
||||
filePath += '/' + fileName
|
||||
@@ -236,10 +236,10 @@
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
if ( err.result === global.CUSTOM_FAIL_RESPONSE.result && (err.message === 'Folder does not exist.' || err.message === 'File does not exist.')
|
||||
if (err.result === global.CUSTOM_FAIL_RESPONSE.result && (err.message === 'Folder does not exist.' || err.message === 'File does not exist.')
|
||||
|| err.code === "The specified key does not exist.") {
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] load -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[INFO] load -> onFileReceived -> err = " + err.message);
|
||||
|
||||
/* In this case we can assume that this is the first execution ever of this bot.*/
|
||||
|
||||
@@ -255,7 +255,7 @@
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] load -> onFileReceived -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] load -> onFileReceived -> err = " + err.message);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
@@ -290,7 +290,7 @@
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] load -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] load -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -328,7 +328,7 @@
|
||||
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] save -> onFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] save -> onFileCreated -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] save -> onFileCreated -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
@@ -348,7 +348,7 @@
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] save -> err = "+ err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] save -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,998 @@
|
||||
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 exchangeAPI
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize() {
|
||||
thisObject = undefined
|
||||
utilities = undefined
|
||||
fileStorage = undefined
|
||||
commons = undefined
|
||||
}
|
||||
|
||||
function initialize(pExchangeAPI, callBackFunction) {
|
||||
try {
|
||||
logger.fileName = MODULE_NAME
|
||||
logger.initialize()
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] initialize -> Entering function.') }
|
||||
|
||||
exchangeAPI = pExchangeAPI
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE)
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] initialize -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function start(multiPeriodDataFiles, timeFrame, timeFrameLabel, currentDay, variable, callBackFunction) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> Entering function.') }
|
||||
|
||||
let chart = {}
|
||||
let mainDependency = {}
|
||||
|
||||
/* 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 timeFrameLabel = marketFilesPeriods[j][1]
|
||||
let dataFiles = multiPeriodDataFiles.get(timeFrameLabel)
|
||||
let products = {}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> Inflating Data Files for timeFrame = ' + timeFrameLabel) }
|
||||
|
||||
if (dataFiles !== undefined) {
|
||||
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame)
|
||||
|
||||
let propertyName = 'at' + timeFrameLabel.replace('-', '')
|
||||
chart[propertyName] = products
|
||||
}
|
||||
}
|
||||
|
||||
for (let j = 0; j < global.dailyFilePeriods.length; j++) {
|
||||
let timeFrameLabel = global.dailyFilePeriods[j][1]
|
||||
let dataFiles = multiPeriodDataFiles.get(timeFrameLabel)
|
||||
let products = {}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> Inflating Data Files for timeFrame = ' + timeFrameLabel) }
|
||||
|
||||
if (dataFiles !== undefined) {
|
||||
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame)
|
||||
|
||||
let propertyName = 'at' + timeFrameLabel.replace('-', '')
|
||||
chart[propertyName] = products
|
||||
}
|
||||
}
|
||||
|
||||
/* Single Files */
|
||||
|
||||
let dataFiles = multiPeriodDataFiles.get('Single Files')
|
||||
let products = {}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> Inflating Data Files from Single Files.') }
|
||||
|
||||
if (dataFiles !== undefined) {
|
||||
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame)
|
||||
|
||||
let propertyName = 'atAnyTimeFrame'
|
||||
chart[propertyName] = products
|
||||
}
|
||||
|
||||
/* Simulation */
|
||||
|
||||
const TRADING_SIMULATION = require('./TradingSimulation.js')
|
||||
let tradingSimulation = TRADING_SIMULATION.newTradingSimulation(bot, logger, UTILITIES)
|
||||
|
||||
let market = bot.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 SNAPSHOTS_FOLDER_NAME = 'Snapshots'
|
||||
|
||||
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000
|
||||
|
||||
let recordsArray = []
|
||||
let conditionsArray = []
|
||||
let strategiesArray = []
|
||||
let positionsArray = []
|
||||
|
||||
let snapshotHeaders
|
||||
let triggerOnSnapshot
|
||||
let takePositionSnapshot
|
||||
|
||||
let tradingSystem = {}
|
||||
|
||||
if (bot.RESUME === true) {
|
||||
readFiles()
|
||||
} else {
|
||||
runSimulation()
|
||||
}
|
||||
|
||||
function readFiles() {
|
||||
|
||||
if (timeFrame > global.dailyFilePeriods[0][0]) {
|
||||
readMarketFiles(runSimulation)
|
||||
} else {
|
||||
readDailyFiles(runSimulation)
|
||||
}
|
||||
}
|
||||
|
||||
function readMarketFiles(callBack) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> Entering function.') }
|
||||
|
||||
readRecordsFile()
|
||||
|
||||
function readRecordsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readRecordsFile -> Entering function.') }
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + SIMULATED_RECORDS_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readRecordsFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
recordsArray = []
|
||||
readConditionsFile()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readRecordsFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readRecordsFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readRecordsFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
recordsArray = JSON.parse(text)
|
||||
readConditionsFile()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readRecordsFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readRecordsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function readConditionsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readConditionsFile -> Entering function.') }
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + CONDITIONS_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readConditionsFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
conditionsArray = []
|
||||
readStrategiesFile()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readConditionsFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readConditionsFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readConditionsFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
conditionsArray = JSON.parse(text)
|
||||
conditionsArray = conditionsArray[1] // conditionsArray[0] = a snapshot of the trading system.
|
||||
readStrategiesFile()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readConditionsFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readConditionsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function readStrategiesFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readStrategiesFile -> Entering function.') }
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + STRATEGIES_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readStrategiesFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
strategiesArray = []
|
||||
readPositionsFile()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readStrategiesFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readStrategiesFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readStrategiesFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
strategiesArray = JSON.parse(text)
|
||||
readPositionsFile()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readStrategiesFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readStrategiesFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function readPositionsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readPositionsFile -> Entering function.') }
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + TRADES_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readMarketFiles -> readPositionsFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
positionsArray = []
|
||||
callBack()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readPositionsFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readPositionsFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readPositionsFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
positionsArray = JSON.parse(text)
|
||||
callBack()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readPositionsFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readMarketFiles -> readPositionsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readDailyFiles(callBack) {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> Entering function.') }
|
||||
|
||||
readRecordsFile()
|
||||
|
||||
function readRecordsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readRecordsFile -> Entering function.') }
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + SIMULATED_RECORDS_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readRecordsFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
recordsArray = []
|
||||
readConditionsFile()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readRecordsFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readRecordsFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readRecordsFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
recordsArray = JSON.parse(text)
|
||||
readConditionsFile()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readRecordsFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readRecordsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function readConditionsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readConditionsFile -> Entering function.') }
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readConditionsFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
conditionsArray = []
|
||||
readStrategiesFile()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readConditionsFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readConditionsFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readConditionsFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
conditionsArray = JSON.parse(text)
|
||||
conditionsArray = conditionsArray[1] // conditionsArray[0] = a snapshot of the trading system.
|
||||
readStrategiesFile()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readConditionsFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readConditionsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function readStrategiesFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readStrategiesFile -> Entering function.') }
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + STRATEGIES_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readStrategiesFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
strategiesArray = []
|
||||
readPositionsFile()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readStrategiesFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readStrategiesFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readStrategiesFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
strategiesArray = JSON.parse(text)
|
||||
readPositionsFile()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readStrategiesFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readStrategiesFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function readPositionsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readPositionsFile -> Entering function.') }
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + TRADES_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileRead, true)
|
||||
|
||||
function onFileRead(err, text) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> readDailyFiles -> readPositionsFile -> onFileRead -> Entering function.') }
|
||||
|
||||
if (err.message === 'File does not exist.') {
|
||||
positionsArray = []
|
||||
callBack()
|
||||
return
|
||||
}
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readPositionsFile -> onFileRead -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readPositionsFile -> onFileRead -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readPositionsFile -> onFileRead -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
positionsArray = JSON.parse(text)
|
||||
callBack()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readPositionsFile -> onFileRead -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> readDailyFiles -> readPositionsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function runSimulation() {
|
||||
tradingSimulation.runSimulation(
|
||||
chart,
|
||||
dataDependencies,
|
||||
timeFrame,
|
||||
timeFrameLabel,
|
||||
currentDay,
|
||||
variable,
|
||||
exchangeAPI,
|
||||
recordsArray,
|
||||
conditionsArray,
|
||||
strategiesArray,
|
||||
positionsArray,
|
||||
writeFiles,
|
||||
callBackFunction)
|
||||
}
|
||||
|
||||
function writeFiles(pTradingSystem, pSnapshotHeaders, pTriggerOnSnapshot, pTakePositionSnapshot) {
|
||||
tradingSystem = pTradingSystem
|
||||
|
||||
snapshotHeaders = pSnapshotHeaders
|
||||
triggerOnSnapshot = pTriggerOnSnapshot
|
||||
takePositionSnapshot = pTakePositionSnapshot
|
||||
|
||||
if (timeFrame > global.dailyFilePeriods[0][0]) {
|
||||
writeMarketFiles()
|
||||
} else {
|
||||
writeDailyFiles()
|
||||
}
|
||||
}
|
||||
|
||||
function writeMarketFiles() {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> Entering function.') }
|
||||
|
||||
writeRecordsFile()
|
||||
|
||||
function writeRecordsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> writeRecordsFile -> Entering function.') }
|
||||
|
||||
let fileContent = JSON.stringify(recordsArray)
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + SIMULATED_RECORDS_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
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 fileContent = JSON.stringify(conditionsArray)
|
||||
|
||||
fileContent = '[' + JSON.stringify(tradingSystem) + ',' + fileContent + ']'
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + CONDITIONS_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
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 fileContent = JSON.stringify(strategiesArray)
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + STRATEGIES_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
writePositionsFile()
|
||||
} 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 writePositionsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> writePositionsFile -> Entering function.') }
|
||||
|
||||
let fileContent = JSON.stringify(positionsArray)
|
||||
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + TRADES_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated)
|
||||
|
||||
function onFileCreated(err) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> writePositionsFile -> onFileCreated -> Entering function.') }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> writePositionsFile -> onFileCreated -> fileContent = ' + fileContent) }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writePositionsFile -> onFileCreated -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writePositionsFile -> onFileCreated -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writePositionsFile -> onFileCreated -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
writeSnapshotFiles()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writePositionsFile -> onFileCreated -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writePositionsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function writeSnapshotFiles() {
|
||||
writeSnapshotFile(triggerOnSnapshot, 'Trigger-On', onFinish)
|
||||
|
||||
function onFinish() {
|
||||
writeSnapshotFile(takePositionSnapshot, 'Take-Position', callBackFunction)
|
||||
}
|
||||
}
|
||||
|
||||
function writeSnapshotFile(snapshotArray, pFileName, callBack) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> writeSnapshotFile -> Entering function.') }
|
||||
|
||||
let fileRecordCounter = 0
|
||||
|
||||
let fileContent = ''
|
||||
let separator = '\r\n'
|
||||
|
||||
parseRecord(snapshotHeaders)
|
||||
|
||||
for (let i = 0; i < snapshotArray.length; i++) {
|
||||
let record = snapshotArray[i]
|
||||
parseRecord(record)
|
||||
fileRecordCounter++
|
||||
}
|
||||
|
||||
function parseRecord(record) {
|
||||
for (let j = 0; j < record.length; j++) {
|
||||
let property = record[j]
|
||||
|
||||
fileContent = fileContent + '' + property
|
||||
if (j !== record.length - 1) {
|
||||
fileContent = fileContent + ','
|
||||
}
|
||||
}
|
||||
fileContent = fileContent + separator
|
||||
}
|
||||
|
||||
fileContent = '' + fileContent + ''
|
||||
|
||||
let fileName = pFileName + '.csv'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + SNAPSHOTS_FOLDER_NAME + '/' + 'Multi-Period-Market' + '/' + timeFrameLabel
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated)
|
||||
|
||||
function onFileCreated(err) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> Entering function.') }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, '[INFO] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> fileContent = ' + fileContent) }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE)
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeDailyFiles() {
|
||||
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 -> writeDailyFiles -> writeRecordsFile -> Entering function.') }
|
||||
|
||||
let fileContent = JSON.stringify(recordsArray)
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + SIMULATED_RECORDS_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
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 fileContent = JSON.stringify(conditionsArray)
|
||||
|
||||
fileContent = '[' + JSON.stringify(tradingSystem) + ',' + fileContent + ']'
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + CONDITIONS_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
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 fileContent = JSON.stringify(strategiesArray)
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + STRATEGIES_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
writePositionsFile()
|
||||
} 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 writePositionsFile() {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeDailyFiles -> writePositionsFile -> Entering function.') }
|
||||
|
||||
let fileContent = JSON.stringify(positionsArray)
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = 'Data.json'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + TRADES_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated)
|
||||
|
||||
function onFileCreated(err) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeDailyFiles -> writePositionsFile -> onFileCreated -> Entering function.') }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, '[INFO] start -> writeDailyFiles -> writePositionsFile -> onFileCreated -> fileContent = ' + fileContent) }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writePositionsFile -> onFileCreated -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writePositionsFile -> onFileCreated -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writePositionsFile -> onFileCreated -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
writeSnapshotFiles()
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writePositionsFile -> onFileCreated -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writePositionsFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function writeSnapshotFiles() {
|
||||
writeSnapshotFile(triggerOnSnapshot, 'Trigger-On', onFinish)
|
||||
|
||||
function onFinish() {
|
||||
writeSnapshotFile(takePositionSnapshot, 'Take-Position', callBackFunction)
|
||||
}
|
||||
}
|
||||
|
||||
function writeSnapshotFile(snapshotArray, pFileName, callBack) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeDailyFiles -> writeSnapshotFile -> Entering function.') }
|
||||
|
||||
let fileRecordCounter = 0
|
||||
|
||||
let fileContent = ''
|
||||
let separator = '\r\n'
|
||||
|
||||
parseRecord(snapshotHeaders)
|
||||
|
||||
for (let i = 0; i < snapshotArray.length; i++) {
|
||||
let record = snapshotArray[i]
|
||||
parseRecord(record)
|
||||
fileRecordCounter++
|
||||
}
|
||||
|
||||
function parseRecord(record) {
|
||||
for (let j = 0; j < record.length; j++) {
|
||||
let property = record[j]
|
||||
|
||||
fileContent = fileContent + '' + property
|
||||
if (j !== record.length - 1) {
|
||||
fileContent = fileContent + ','
|
||||
}
|
||||
}
|
||||
fileContent = fileContent + separator
|
||||
}
|
||||
|
||||
fileContent = '' + fileContent + ''
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2)
|
||||
let fileName = pFileName + '.csv'
|
||||
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + SNAPSHOTS_FOLDER_NAME + '/' + 'Multi-Period-Daily' + '/' + timeFrameLabel + '/' + dateForPath
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated)
|
||||
|
||||
function onFileCreated(err) {
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> Entering function.') }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, '[INFO] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> fileContent = ' + fileContent) }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> err = ' + err.stack)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> filePath = ' + filePath)
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> market = ' + market.baseAsset + '_' + market.quotedAsset)
|
||||
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE)
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, '[ERROR] start -> err = ' + err.stack)
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
exports.newTradingEngine = function newTradingEngine(bot, logger) {
|
||||
|
||||
const MODULE_NAME = 'Trading Engine'
|
||||
|
||||
let thisObject = {
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize() {
|
||||
/* Here we will go through all the nodes in the Trading Engine hiriarchy and apply the initial value to the value property when needed */
|
||||
|
||||
if (bot.TRADING_ENGINE.isInitialized !== true || bot.RESUME === false) {
|
||||
bot.TRADING_ENGINE.isInitialized = true
|
||||
initializeNode(bot.TRADING_ENGINE)
|
||||
}
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
|
||||
}
|
||||
|
||||
function initializeNode(node) {
|
||||
if (node === undefined) { return }
|
||||
|
||||
/* Here we initialize the node value */
|
||||
if (node.config !== undefined) {
|
||||
if (node.config.initialValue !== undefined) {
|
||||
node.value = node.config.initialValue
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we go down through all this node children */
|
||||
let nodeDefinition = bot.APP_SCHEMA_MAP.get(node.type)
|
||||
if (nodeDefinition === undefined) { return }
|
||||
|
||||
if (nodeDefinition.properties !== undefined) {
|
||||
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
|
||||
for (let i = 0; i < nodeDefinition.properties.length; i++) {
|
||||
let property = nodeDefinition.properties[i]
|
||||
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
if (property.name !== previousPropertyName) {
|
||||
if (node[property.name] !== undefined) {
|
||||
initializeNode(node[property.name])
|
||||
}
|
||||
previousPropertyName = property.name
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'array': {
|
||||
if (node[property.name] !== undefined) {
|
||||
let nodePropertyArray = node[property.name]
|
||||
object[property.name] = []
|
||||
for (let m = 0; m < nodePropertyArray.length; m++) {
|
||||
initializeNode(nodePropertyArray[m])
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
-981
@@ -1,981 +0,0 @@
|
||||
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 exchangeAPI;
|
||||
|
||||
return thisObject;
|
||||
|
||||
function finalize() {
|
||||
thisObject = undefined
|
||||
utilities = undefined
|
||||
fileStorage = undefined
|
||||
commons = undefined
|
||||
}
|
||||
|
||||
function initialize(pExchangeAPI, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
logger.fileName = MODULE_NAME;
|
||||
logger.initialize();
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
|
||||
|
||||
exchangeAPI = pExchangeAPI;
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function start(multiPeriodDataFiles, timeFrame, timeFrameLabel, currentDay, interExecutionMemory, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
|
||||
|
||||
let chart = {}
|
||||
let mainDependency = {}
|
||||
|
||||
/* 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 timeFrameLabel = marketFilesPeriods[j][1]
|
||||
let dataFiles = multiPeriodDataFiles.get(timeFrameLabel)
|
||||
let products = {}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Inflating Data Files for timeFrame = " + timeFrameLabel); }
|
||||
|
||||
if (dataFiles !== undefined) {
|
||||
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame)
|
||||
|
||||
let propertyName = 'at' + timeFrameLabel.replace('-', '');
|
||||
chart[propertyName] = products
|
||||
}
|
||||
}
|
||||
|
||||
for (let j = 0; j < global.dailyFilePeriods.length; j++) {
|
||||
|
||||
let timeFrameLabel = global.dailyFilePeriods[j][1]
|
||||
let dataFiles = multiPeriodDataFiles.get(timeFrameLabel)
|
||||
let products = {}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Inflating Data Files for timeFrame = " + timeFrameLabel); }
|
||||
|
||||
if (dataFiles !== undefined) {
|
||||
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame)
|
||||
|
||||
let propertyName = 'at' + timeFrameLabel.replace('-', '');
|
||||
chart[propertyName] = products
|
||||
}
|
||||
}
|
||||
|
||||
/* Single Files */
|
||||
|
||||
let dataFiles = multiPeriodDataFiles.get('Single Files')
|
||||
let products = {}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Inflating Data Files from Single Files."); }
|
||||
|
||||
if (dataFiles !== undefined) {
|
||||
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame)
|
||||
|
||||
let propertyName = 'atAnyTimeFrame';
|
||||
chart[propertyName] = products
|
||||
}
|
||||
|
||||
/* Simulation */
|
||||
|
||||
const TRADING_SIMULATION = require('./TradingSimulation.js');
|
||||
let tradingSimulation = TRADING_SIMULATION.newTradingSimulation(bot, logger, UTILITIES);
|
||||
|
||||
let market = bot.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,
|
||||
timeFrame,
|
||||
timeFrameLabel,
|
||||
currentDay,
|
||||
interExecutionMemory,
|
||||
exchangeAPI,
|
||||
writeFiles,
|
||||
callBackFunction)
|
||||
|
||||
function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray) {
|
||||
|
||||
tradingSystem = pTradingSystem
|
||||
recordsArray = pRecordsArray
|
||||
conditionsArray = pConditionsArray
|
||||
strategiesArray = pStrategiesArray
|
||||
tradesArray = pTradesArray
|
||||
|
||||
if (timeFrame > 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.quotedAsset + "," +
|
||||
record.marketBaseAsset + "," +
|
||||
record.marketQuotedAsset + "," +
|
||||
record.positionPeriods + "," +
|
||||
record.positionDays + "," +
|
||||
record.distanceToLastTriggerOn + "," +
|
||||
record.distanceToLastTriggerOff + "," +
|
||||
record.distanceToLastTakePosition + "," +
|
||||
record.distanceToLastClosePosition + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
fileRecordCounter++;
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrameLabel;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
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 = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + CONDITIONS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrameLabel;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
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 + "," +
|
||||
'"' + record.triggerOnSituation + '"' + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
fileRecordCounter++;
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + STRATEGIES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrameLabel;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
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 + "," +
|
||||
'"' + record.takePositionSituation + '"' + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
fileRecordCounter++;
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + TRADES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrameLabel;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
callBackFunction(err);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
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.quotedAsset + "," +
|
||||
record.marketBaseAsset + "," +
|
||||
record.marketQuotedAsset + "," +
|
||||
record.positionPeriods + "," +
|
||||
record.positionDays + "," +
|
||||
record.distanceToLastTriggerOn + "," +
|
||||
record.distanceToLastTriggerOff + "," +
|
||||
record.distanceToLastTakePosition + "," +
|
||||
record.distanceToLastClosePosition + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
fileRecordCounter++;
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
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.quotedAsset + "," +
|
||||
record.marketBaseAsset + "," +
|
||||
record.marketQuotedAsset + "," +
|
||||
record.positionPeriods + "," +
|
||||
record.positionDays + "," +
|
||||
record.distanceToLastTriggerOn + "," +
|
||||
record.distanceToLastTriggerOff + "," +
|
||||
record.distanceToLastTakePosition + "," +
|
||||
record.distanceToLastClosePosition + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
fileRecordCounter++;
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
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 = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + CONDITIONS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
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 + "," +
|
||||
'"' + record.triggerOnSituation + '"' + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
fileRecordCounter++;
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + STRATEGIES_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
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 + "," +
|
||||
'"' + record.takePositionSituation + '"' + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
fileRecordCounter++;
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + TRADES_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(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.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
callBackFunction(err);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Generated
+9
-9
@@ -5,9 +5,9 @@
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"ccxt": {
|
||||
"version": "1.25.80",
|
||||
"resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.25.80.tgz",
|
||||
"integrity": "sha512-AUWagxMa8PMexRabbktWezlmVacj6L2Ep4844ebIXUOyME2Ommg7O/9/pq0F2Ne1IHcJnNJzHrMYQvkh2gBtlw=="
|
||||
"version": "1.27.45",
|
||||
"resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.27.45.tgz",
|
||||
"integrity": "sha512-4ADlbcIWDzIWjtLvsrtux5jMFj7pU4kVuiqtI2Btq6NEhQ4r/4+LirXdEFlCF6/wIU3XSHabxMd/8nu8HC1KJw=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
@@ -48,9 +48,9 @@
|
||||
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ=="
|
||||
},
|
||||
"telegraf": {
|
||||
"version": "3.37.0",
|
||||
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.37.0.tgz",
|
||||
"integrity": "sha512-V3448qwfOolBqkIc87yxjW4zMvR2P6AIF24pPTlX9WhZPwA1TF/x3nQhnWPRLtGh2SJuvDcr83iTkXPXT7Opnw==",
|
||||
"version": "3.38.0",
|
||||
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.38.0.tgz",
|
||||
"integrity": "sha512-va4VlrKWp64JrowFoZX/NPzzA6q38kvaIukVXOWFO1V+jR1G8+hCfgJy4TX8Z3rwLJzwaBEet1QhikHDRZWl3A==",
|
||||
"requires": {
|
||||
"debug": "4.1.1",
|
||||
"minimist": "1.2.5",
|
||||
@@ -66,9 +66,9 @@
|
||||
"integrity": "sha512-njVv1EAhIZnmQVLocZEADYUyqA1WIXuVcDYlsp+mXua/XB0pxx+PKtMSPeZ/EE4wPWTw9h/hA9ASTT6yQelkiw=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
|
||||
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ=="
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
|
||||
"integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ function finalizeSessions() {
|
||||
}
|
||||
}
|
||||
|
||||
process.on('exit', function (code) {
|
||||
process.on('exit', function (config) {
|
||||
|
||||
if (global.TASK_NODE !== undefined) {
|
||||
/* We send an event signaling that the Task is being terminated. */
|
||||
@@ -68,7 +68,7 @@ process.on('exit', function (code) {
|
||||
global.EVENT_SERVER_CLIENT = undefined
|
||||
}
|
||||
|
||||
//console.log('[INFO] Task Server -> server -> process.on.exit -> About to exit -> code = ' + code)
|
||||
//console.log('[INFO] Task Server -> server -> process.on.exit -> About to exit -> config = ' + config)
|
||||
})
|
||||
|
||||
/* 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. */
|
||||
@@ -84,7 +84,7 @@ process.on('message', message => {
|
||||
let key = global.TASK_NODE.name + '-' + global.TASK_NODE.type + '-' + global.TASK_NODE.id
|
||||
console.log('[INFO] Task Server -> server -> process.on -> Stopping Task ' + key + '. Nodejs process will be exited in less than 1 minute.')
|
||||
setTimeout(global.EXIT_NODE_PROCESS, 60000);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ global.EXIT_NODE_PROCESS = function exitProcess() {
|
||||
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 config = global.TASK_NODE.bot.processes[i].config
|
||||
let process = global.TASK_NODE.bot.processes[i]
|
||||
|
||||
key = process.name + '-' + process.type + '-' + process.id
|
||||
@@ -138,7 +138,7 @@ let taskId = process.argv[2] // reading what comes as an argument of the nodejs
|
||||
/* Setting up the global Event Handler */
|
||||
|
||||
let EVENT_SERVER_CLIENT = require('./EventServerClient.js');
|
||||
|
||||
|
||||
global.EVENT_SERVER_CLIENT = EVENT_SERVER_CLIENT.newEventsServerClient()
|
||||
global.EVENT_SERVER_CLIENT.initialize(preLoader)
|
||||
global.STOP_TASK_GRACEFULLY = false;
|
||||
@@ -162,7 +162,7 @@ function preLoader() {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
try {
|
||||
//console.log('[INFO] Task Server -> server -> preLoader -> Waiting for event to start debugging...')
|
||||
global.EVENT_SERVER_CLIENT.listenToEvent('Task Server', 'Debug Task Started', undefined, 'Task Server', undefined, startDebugging)
|
||||
function startDebugging(message) {
|
||||
@@ -190,15 +190,15 @@ function bootLoader() {
|
||||
|
||||
function taskHearBeat() {
|
||||
|
||||
/* The heartbeat event is raised at the event handler of the instance of this task, created at the UI. */
|
||||
/* The heartbeat event is raised at the event handler of the instance of this task, created at the UI. */
|
||||
let event = {
|
||||
seconds: (new Date()).getSeconds()
|
||||
}
|
||||
global.EVENT_SERVER_CLIENT.raiseEvent(key, 'Heartbeat', event)
|
||||
global.EVENT_SERVER_CLIENT.raiseEvent(key, 'Heartbeat', event)
|
||||
}
|
||||
|
||||
for (let processIndex = 0; processIndex < global.TASK_NODE.bot.processes.length; processIndex++) {
|
||||
let code = global.TASK_NODE.bot.processes[processIndex].code
|
||||
let config = global.TASK_NODE.bot.processes[processIndex].config
|
||||
|
||||
/* Validate that the minimun amount of input required are defined. */
|
||||
|
||||
@@ -257,17 +257,17 @@ function bootLoader() {
|
||||
continue
|
||||
}
|
||||
|
||||
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.code.codeName === undefined) {
|
||||
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.config.codeName === undefined) {
|
||||
console.log("[WARN] Task Server -> server -> bootLoader -> Process Definition without a codeName defined. -> Process Definition = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex].referenceParent));
|
||||
continue
|
||||
}
|
||||
|
||||
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.code.codeName === undefined) {
|
||||
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.config.codeName === undefined) {
|
||||
console.log("[WARN] 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.processes[processIndex].referenceParent.parentNode.parentNode.code.codeName === undefined) {
|
||||
if (global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName === undefined) {
|
||||
console.log("[WARN] Task Server -> server -> bootLoader -> Data Mine without a codeName defined. -> Data Mine Definition = " + JSON.stringify(global.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode));
|
||||
continue
|
||||
}
|
||||
@@ -278,7 +278,7 @@ function bootLoader() {
|
||||
|
||||
function startRoot(processIndex) {
|
||||
|
||||
// console.log('[INFO] Task Server -> server -> startRoot -> Entering function. ')
|
||||
// console.log('[INFO] Task Server -> server -> startRoot -> Entering function. ')
|
||||
|
||||
const ROOT_MODULE = require('./Root')
|
||||
let root = ROOT_MODULE.newRoot()
|
||||
@@ -299,13 +299,13 @@ global.getPercentage = function (fromDate, currentDate, lastDate) {
|
||||
if ((lastDays - fromDays) === 0) {
|
||||
percentage = 100
|
||||
}
|
||||
return percentage
|
||||
return percentage
|
||||
}
|
||||
|
||||
global.areEqualDates = function (date1, date2) {
|
||||
let day1Days = Math.trunc(date1.valueOf() / ONE_DAY_IN_MILISECONDS)
|
||||
let day2Days = Math.trunc(date2.valueOf() / ONE_DAY_IN_MILISECONDS)
|
||||
|
||||
|
||||
if (day1Days === day2Days) {
|
||||
return true
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user