Merge pull request #150 from AAMasters/develop

Beta 5
This commit is contained in:
Luis Fernando Molina authored and GitHub committed 2020-06-01 19:01:40 +02:00
commit 31e442bd2a
22 files changed
+4018 -6354

No files matched your search

-1127
View File
File diff suppressed because it is too large. Load diff
+37 -30
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 = {
+24 -24
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}
+998
View File
@@ -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)
}
}
}
+69
View File
@@ -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
View File
@@ -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);
}
}
};
-3167
View File
File diff suppressed because it is too large. Load diff
+9 -9
View File
@@ -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=="
}
}
}
+15 -15
View File
@@ -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 {