diff --git a/.vs/AACloud/v15/.suo b/.vs/AACloud/v15/.suo
index 84d954d6a..a77841872 100644
Binary files a/.vs/AACloud/v15/.suo and b/.vs/AACloud/v15/.suo differ
diff --git a/Assistant.js b/Assistant.js
index 04e5dd757..141e5a458 100644
--- a/Assistant.js
+++ b/Assistant.js
@@ -91,78 +91,128 @@
try {
candleArray = JSON.parse(text);
- if (bot.backTestingMode === true) {
+ switch (bot.runMode) {
- logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Backtest Mode detected.");
+ case "Live": {
- /* We need to find the candle at which the process is currently running. */
+ logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Live Mode detected.");
- for (let i = 0; i < candleArray.length; i++) {
+ let lastCandleRecord = candleArray[candleArray.length - 1]; // The last candle contains at its close value the market rate.
let candle = {
- open: candleArray[i][2],
- close: candleArray[i][3],
- min: candleArray[i][0],
- max: candleArray[i][1],
- begin: candleArray[i][4],
- end: candleArray[i][5]
+ open: lastCandleRecord[2],
+ close: lastCandleRecord[3],
+ min: lastCandleRecord[0],
+ max: lastCandleRecord[1],
+ begin: lastCandleRecord[4],
+ end: lastCandleRecord[5]
};
- if (bot.processDatetime.valueOf() >= candle.begin && bot.processDatetime.valueOf() < candle.end) {
+ marketRate = candle.close;
+ marketRate = Number(marketRate.toFixed(8));
- marketRate = (candle.open + candle.close) / 2;
- marketRate = Number(marketRate.toFixed(8));
+ /*
+ Now we verify that this candle is not too old. Lets say no more than 10 minutes old. This could happen if the datasets for
+ any reason stops being updated.
+ */
- /* The Backtest Mode simulates that every trade posted is executed.
- In order to do this, we will take all open orders from the context and create a trades array similar to the one returned by the Exchange. */
+ let delay = (bot.processDatetime.valueOf() - candle.begin) / 1000 / 60;
- validateExchangeSyncronicity();
+ logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Market Rate " + delay + " minutes old.");
+
+ if (delay > 30) {
+
+ logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> Market Rate more than 10 minutes old. Retrying later.");
+
+ callBackFunction(global.DEFAULT_RETRY_RESPONSE);
return;
}
- }
- logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> No candle found for the current Process Datetime.");
- logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> bot.processDatetime = " + bot.processDatetime);
- callBackFunction(global.DEFAULT_FAIL_RESPONSE);
- return;
-
- } else { // We are running LIVE Mode.
-
- logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Live Mode detected.");
-
- let lastCandleRecord = candleArray[candleArray.length - 1]; // The last candle contains at its close value the market rate.
-
- let candle = {
- open: lastCandleRecord[2],
- close: lastCandleRecord[3],
- min: lastCandleRecord[0],
- max: lastCandleRecord[1],
- begin: lastCandleRecord[4],
- end: lastCandleRecord[5]
- };
-
- marketRate = candle.close;
- marketRate = Number(marketRate.toFixed(8));
-
- /*
- Now we verify that this candle is not too old. Lets say no more than 2 minutes old. This could happen if the datasets for
- any reason stops being updated.
- */
-
- let delay = (bot.processDatetime.valueOf() - candle.begin) / 1000 / 60;
-
- logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Market Rate " + delay + " minutes old." );
-
- if (delay > 30) {
-
- logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> Market Rate more than 10 minutes old. Retrying later.");
-
- callBackFunction(global.DEFAULT_RETRY_RESPONSE);
+ validateExchangeSyncronicity();
return;
}
- validateExchangeSyncronicity();
- return;
+ case "Backtest": {
+
+ logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Backtest Mode detected.");
+
+ /* We need to find the candle at which the process is currently running. */
+
+ for (let i = 0; i < candleArray.length; i++) {
+
+ let candle = {
+ open: candleArray[i][2],
+ close: candleArray[i][3],
+ min: candleArray[i][0],
+ max: candleArray[i][1],
+ begin: candleArray[i][4],
+ end: candleArray[i][5]
+ };
+
+ if (bot.processDatetime.valueOf() >= candle.begin && bot.processDatetime.valueOf() < candle.end) {
+
+ marketRate = (candle.open + candle.close) / 2;
+ marketRate = Number(marketRate.toFixed(8));
+
+ /* The Backtest Mode simulates that every trade posted is executed.
+ In order to do this, we will take all open orders from the context and create a trades array similar to the one returned by the Exchange. */
+
+ validateExchangeSyncronicity();
+ return;
+ }
+ }
+
+ logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> No candle found for the current Process Datetime.");
+ logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> bot.processDatetime = " + bot.processDatetime);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
+
+ case "Competition": {
+
+ logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Competition Mode detected.");
+
+ let lastCandleRecord = candleArray[candleArray.length - 1]; // The last candle contains at its close value the market rate.
+
+ let candle = {
+ open: lastCandleRecord[2],
+ close: lastCandleRecord[3],
+ min: lastCandleRecord[0],
+ max: lastCandleRecord[1],
+ begin: lastCandleRecord[4],
+ end: lastCandleRecord[5]
+ };
+
+ marketRate = candle.close;
+ marketRate = Number(marketRate.toFixed(8));
+
+ /*
+ Now we verify that this candle is not too old. Lets say no more than 10 minutes old. This could happen if the datasets for
+ any reason stops being updated.
+ */
+
+ let delay = (bot.processDatetime.valueOf() - candle.begin) / 1000 / 60;
+
+ logger.write("[INFO] initialize -> getMarketRate -> onFileReceived -> Market Rate " + delay + " minutes old.");
+
+ if (delay > 30) {
+
+ logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> Market Rate more than 10 minutes old. Retrying later.");
+
+ callBackFunction(global.DEFAULT_RETRY_RESPONSE);
+ return;
+ }
+
+ validateExchangeSyncronicity();
+ return;
+ }
+
+ default: {
+ logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> Unexpected bot.runMode.");
+ logger.write("[ERROR] initialize -> getMarketRate -> onFileReceived -> bot.runMode = " + bot.runMode);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
} catch (err) {
@@ -250,18 +300,36 @@
*/
- if (bot.backTestingMode === true) {
+ switch (bot.runMode) {
- if (FULL_LOG === true) { logger.write("[INFO] getPositionsAtExchange -> Backtest Mode Detected."); }
+ case "Live": {
- let exchangePositions = []; // We simulate all positions were executed.
+ if (FULL_LOG === true) { logger.write("[INFO] getPositionsAtExchange -> Live Mode Detected."); }
+ exchangeAPI.getOpenPositions(global.MARKET, onResponse);
+ break;
+ }
- onResponse(global.DEFAULT_OK_RESPONSE, exchangePositions);
- } else {
+ case "Backtest": {
- if (FULL_LOG === true) { logger.write("[INFO] getPositionsAtExchange -> Live Mode Detected."); }
- exchangeAPI.getOpenPositions(global.MARKET, onResponse);
+ if (FULL_LOG === true) { logger.write("[INFO] getPositionsAtExchange -> Backtest Mode Detected."); }
+ let exchangePositions = []; // We simulate all positions were executed.
+ onResponse(global.DEFAULT_OK_RESPONSE, exchangePositions);
+ break;
+ }
+ case "Competition": {
+
+ if (FULL_LOG === true) { logger.write("[INFO] getPositionsAtExchange -> Competition Mode Detected."); }
+ exchangeAPI.getOpenPositions(global.MARKET, onResponse);
+ break;
+ }
+
+ default: {
+ logger.write("[ERROR] getPositionsAtExchange -> Unexpected bot.runMode.");
+ logger.write("[ERROR] getPositionsAtExchange -> bot.runMode = " + bot.runMode);
+ callBack(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
function onResponse(err, pExchangePositions) {
@@ -481,47 +549,66 @@
*/
- if (bot.backTestingMode === true) {
+ switch (bot.runMode) {
- if (FULL_LOG === true) { logger.write("[INFO] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Backtest Mode Detected."); }
+ case "Live": {
- let trades = [];
+ if (FULL_LOG === true) { logger.write("[INFO] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Live Mode Detected."); }
+ exchangeAPI.getExecutedTrades(pPositionId, onResponse);
+ return;
- /* We look for the position at the executionContext */
-
- for (let i = 0; i < context.executionContext.positions.length; i++) {
-
- let thisPosition = context.executionContext.positions[i];
-
- if (thisPosition.id === pPositionId) {
-
- let trade = {
- id: Math.trunc(Math.random(1) * 1000000),
- type: thisPosition.type,
- rate: thisPosition.rate,
- amountA: thisPosition.amountA,
- amountB: thisPosition.amountB,
- fee: 0,
- date: (new Date()).valueOf()
- }
-
- trades.push(trade);
-
- onResponse(global.DEFAULT_OK_RESPONSE, trades);
-
- return;
- }
}
- logger.write("[ERROR] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Position not found at Executioin Context.");
- callBack(global.DEFAULT_FAIL_RESPONSE);
- return;
+ case "Backtest": {
- } else {
+ if (FULL_LOG === true) { logger.write("[INFO] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Backtest Mode Detected."); }
- if (FULL_LOG === true) { logger.write("[INFO] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Live Mode Detected."); }
- exchangeAPI.getExecutedTrades(pPositionId, onResponse);
+ let trades = [];
+ /* We look for the position at the executionContext */
+
+ for (let i = 0; i < context.executionContext.positions.length; i++) {
+
+ let thisPosition = context.executionContext.positions[i];
+
+ if (thisPosition.id === pPositionId) {
+
+ let trade = {
+ id: Math.trunc(Math.random(1) * 1000000),
+ type: thisPosition.type,
+ rate: thisPosition.rate,
+ amountA: thisPosition.amountA,
+ amountB: thisPosition.amountB,
+ fee: 0,
+ date: (new Date()).valueOf()
+ }
+
+ trades.push(trade);
+
+ onResponse(global.DEFAULT_OK_RESPONSE, trades);
+
+ return;
+ }
+ }
+
+ logger.write("[ERROR] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Position not found at Executioin Context.");
+ callBack(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
+
+ case "Competition": {
+
+ if (FULL_LOG === true) { logger.write("[INFO] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Competition Mode Detected."); }
+ exchangeAPI.getExecutedTrades(pPositionId, onResponse);
+ return;
+ }
+
+ default: {
+ logger.write("[ERROR] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> Unexpected bot.runMode.");
+ logger.write("[ERROR] ordersExecutionCheck -> loopBody -> positionNotFound -> getPositionTradesAtExchange -> bot.runMode = " + bot.runMode);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
function onResponse(err, pTrades) {
@@ -839,22 +926,40 @@
/* All validations passed, we proceed. */
- if (bot.backTestingMode === true) {
+ switch (bot.runMode) {
- if (pRate !== marketRate) {
+ case "Live": {
- logger.write("[ERROR] putPosition -> Input Validations -> putPosition Rate can not be different to marketRate while in Backtesting Mode. ");
- onResponse(global.DEFAULT_FAIL_RESPONSE, positionId);
+ exchangeAPI.putPosition(global.MARKET, pType, pRate, pAmountA, pAmountB, onResponse);
+ return;
}
- let positionId = Math.trunc(Math.random(1) * 1000000);
- if (FULL_LOG === true) { logger.write("[INFO] putPosition -> Simulating Exchange Response -> orderId = " + positionId); }
- onResponse(global.DEFAULT_OK_RESPONSE, positionId);
+ case "Backtest": {
- } else {
+ if (pRate !== marketRate) {
- exchangeAPI.putPosition(global.MARKET, pType, pRate, pAmountA, pAmountB, onResponse);
+ logger.write("[ERROR] putPosition -> Input Validations -> putPosition Rate can not be different to marketRate while in Backtesting Mode. ");
+ onResponse(global.DEFAULT_FAIL_RESPONSE, positionId);
+ }
+ let positionId = Math.trunc(Math.random(1) * 1000000);
+ if (FULL_LOG === true) { logger.write("[INFO] putPosition -> Simulating Exchange Response -> orderId = " + positionId); }
+ onResponse(global.DEFAULT_OK_RESPONSE, positionId);
+ return;
+ }
+
+ case "Competition": {
+
+ exchangeAPI.putPosition(global.MARKET, pType, pRate, pAmountA, pAmountB, onResponse);
+ return;
+ }
+
+ default: {
+ logger.write("[ERROR] putPosition -> Unexpected bot.runMode.");
+ logger.write("[ERROR] putPosition -> bot.runMode = " + bot.runMode);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
function onResponse(err, pPositionId) {
@@ -938,16 +1043,34 @@
if (FULL_LOG === true) { logger.write("[INFO] movePosition -> pPosition = " + JSON.stringify(pPosition)); }
if (FULL_LOG === true) { logger.write("[INFO] movePosition -> pNewRate = " + pNewRate); }
- if (bot.backTestingMode === true) {
+ switch (bot.runMode) {
- let positionId = Math.trunc(Math.random(1) * 1000000);
- if (FULL_LOG === true) { logger.write("[INFO] putPosition -> Simulating Exchange Response -> orderId = " + positionId); }
- onResponse(global.DEFAULT_OK_RESPONSE, positionId);
+ case "Live": {
- } else {
+ exchangeAPI.movePosition(pPosition, pNewRate, onResponse);
+ return;
+ }
- exchangeAPI.movePosition(pPosition, pNewRate, onResponse);
+ case "Backtest": {
+ let positionId = Math.trunc(Math.random(1) * 1000000);
+ if (FULL_LOG === true) { logger.write("[INFO] putPosition -> Simulating Exchange Response -> orderId = " + positionId); }
+ onResponse(global.DEFAULT_OK_RESPONSE, positionId);
+ return;
+ }
+
+ case "Competition": {
+
+ exchangeAPI.movePosition(pPosition, pNewRate, onResponse);
+ return;
+ }
+
+ default: {
+ logger.write("[ERROR] movePosition -> Unexpected bot.runMode.");
+ logger.write("[ERROR] movePosition -> bot.runMode = " + bot.runMode);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
function onResponse(err, pPositionId) {
diff --git a/Context.js b/Context.js
index c462c30f9..967cb7e23 100644
--- a/Context.js
+++ b/Context.js
@@ -78,6 +78,8 @@
let statusDependencies;
+ let runIndex; // This is the index for this run and depends on the runMode.
+
return thisObject;
function initialize(pStatusDependencies, callBackFunction) {
@@ -166,6 +168,34 @@
} else {
+ switch (bot.runMode) {
+
+ case "Live": {
+
+ runIndex = thisObject.statusReport.liveRuns.length - 1;
+ break;
+ }
+
+ case "Backtest": {
+
+ runIndex = thisObject.statusReport.backtestRuns.length - 1;
+ break;
+ }
+
+ case "Competition": {
+
+ runIndex = thisObject.statusReport.competitionRuns.length - 1;
+ break;
+ }
+
+ default: {
+ logger.write("[ERROR] initialize -> createConext -> Unexpected bot.runMode.");
+ logger.write("[ERROR] initialize -> createConext -> bot.runMode = " + bot.runMode);
+ callBack(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
+ }
+
getExecutionHistory(callBack);
}
@@ -182,7 +212,7 @@
if (FULL_LOG === true) { logger.write("[INFO] initialize -> getExecutionHistory -> Entering function."); }
- let fileName = "Execution.History." + thisObject.statusReport.runType + "." + thisObject.statusReport.runIndex + ".json";
+ let fileName = "Execution.History." + bot.runMode + "." + runIndex + ".json";
let filePath = bot.filePathRoot + "/Output/" + bot.process;
if (FULL_LOG === true) { logger.write("[INFO] initialize -> getExecutionHistory -> fileName = " + fileName); }
@@ -208,9 +238,12 @@
/* 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.buyAvgRate = thisObject.executionHistory[thisObject.executionHistory.length-1][1];
thisObject.newHistoryRecord.sellAvgRate = thisObject.executionHistory[thisObject.executionHistory.length - 1][2];
+ thisObject.newHistoryRecord.buyAvgRate = thisObject.executionHistory[1];
+ thisObject.newHistoryRecord.sellAvgRate = thisObject.executionHistory[2];
+
getExecutionContext(callBack);
} catch (err) {
@@ -241,25 +274,37 @@
if (FULL_LOG === true) { logger.write("[INFO] initialize -> getExecutionContext -> Entering function."); }
let date;
- let runType = thisObject.statusReport.runType;
- switch (runType) {
+ switch (bot.runMode) {
- case "Backtest": {
- date = new Date(thisObject.statusReport.backtestRuns[thisObject.statusReport.runIndex].lastExecution);
- thisObject.statusReport.backtestRuns[thisObject.statusReport.runIndex].lastExecution = bot.processDatetime;
+ case "Live": {
+ date = new Date(thisObject.statusReport.liveRuns[runIndex].lastExecution);
+ thisObject.statusReport.liveRuns[runIndex].lastExecution = bot.processDatetime;
+ thisObject.statusReport.liveRuns[runIndex].endDatetime = bot.processDatetime;
break;
}
- case "Live": {
- date = new Date(thisObject.statusReport.liveRuns[thisObject.statusReport.runIndex].lastExecution);
- thisObject.statusReport.liveRuns[thisObject.statusReport.runIndex].lastExecution = bot.processDatetime;
- thisObject.statusReport.liveRuns[thisObject.statusReport.runIndex].endDatetime = bot.processDatetime;
+ case "Backtest": {
+ date = new Date(thisObject.statusReport.backtestRuns[runIndex].lastExecution);
+ thisObject.statusReport.backtestRuns[runIndex].lastExecution = bot.processDatetime;
break;
}
+
+ case "Competition": {
+ date = new Date(thisObject.statusReport.competitionRuns[runIndex].lastExecution);
+ thisObject.statusReport.competitionRuns[runIndex].lastExecution = bot.processDatetime;
+ break;
+ }
+
+ default: {
+ logger.write("[ERROR] initialize -> getExecutionContext -> Unexpected bot.runMode.");
+ logger.write("[ERROR] initialize -> getExecutionContext -> bot.runMode = " + bot.runMode);
+ callBack(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
- let fileName = "Execution.Context." + thisObject.statusReport.runType + "." + thisObject.statusReport.runIndex + ".json";
+ let fileName = "Execution.Context." + bot.runMode + "." + 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/" + bot.process + '/' + dateForPath;
@@ -327,43 +372,18 @@
*/
- let runType;
-
- if (bot.backTestingMode === true) {
- runType = "Backtest";
- } else {
- runType = "Live";
- }
-
/* Here, we dont know if the Status Report was ever created or not. To test that we do this. */
- if (thisObject.statusReport.runType === undefined) { // This means that the Status Report does not exist.
+ if (thisObject.statusReport.liveRuns === undefined) { // This means that the Status Report does not exist.
thisObject.statusReport = {
- runType: runType,
- runIndex: 0,
liveRuns: [],
- backtestRuns: []
+ backtestRuns: [],
+ competitionRuns: []
};
-
}
- thisObject.statusReport.runType = runType;
-
- switch (runType) {
-
- case "Backtest": {
-
- let runContent = {
- beginDatetime: (new Date(bot.timePeriod.beginDatetime)).valueOf(),
- endDatetime: (new Date(bot.timePeriod.endDatetime)).valueOf(),
- lastExecution: bot.processDatetime
- };
-
- thisObject.statusReport.backtestRuns.push(runContent);
- thisObject.statusReport.runIndex = thisObject.statusReport.backtestRuns.length - 1;
- break;
- }
+ switch (bot.runMode) {
case "Live": {
@@ -374,9 +394,42 @@
};
thisObject.statusReport.liveRuns.push(runContent);
- thisObject.statusReport.runIndex = thisObject.statusReport.liveRuns.length - 1;
+ runIndex = thisObject.statusReport.liveRuns.length - 1;
break;
}
+
+ case "Backtest": {
+
+ let runContent = {
+ beginDatetime: (new Date(bot.backtest.beginDatetime)).valueOf(),
+ endDatetime: (new Date(bot.backtest.endDatetime)).valueOf(),
+ lastExecution: bot.processDatetime
+ };
+
+ thisObject.statusReport.backtestRuns.push(runContent);
+ runIndex = thisObject.statusReport.backtestRuns.length - 1;
+ break;
+ }
+
+ case "Competition": {
+
+ let runContent = {
+ beginDatetime: (new Date(bot.competition.beginDatetime)).valueOf(),
+ endDatetime: (new Date(bot.competition.endDatetime)).valueOf(),
+ lastExecution: bot.processDatetime
+ };
+
+ thisObject.statusReport.competitionRuns.push(runContent);
+ runIndex = thisObject.statusReport.competitionRuns.length - 1;
+ break;
+ }
+
+ default: {
+ logger.write("[ERROR] initialize -> createConext -> Unexpected bot.runMode.");
+ logger.write("[ERROR] initialize -> createConext -> bot.runMode = " + bot.runMode);
+ callBack(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
thisObject.executionHistory = [];
@@ -469,7 +522,7 @@
if (FULL_LOG === true) { logger.write("[INFO] saveThemAll -> writeExecutionContext -> Entering function."); }
- let fileName = "Execution.Context." + thisObject.statusReport.runType + "." + thisObject.statusReport.runIndex +".json";
+ let fileName = "Execution.Context." + bot.runMode + "." + 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/" + bot.process + '/' + dateForPath;
@@ -530,7 +583,7 @@
if (FULL_LOG === true) { logger.write("[INFO] saveThemAll -> writeExucutionHistory -> Entering function."); }
- let fileName = "Execution.History." + thisObject.statusReport.runType + "." + thisObject.statusReport.runIndex + ".json";
+ let fileName = "Execution.History." + bot.runMode + "." + runIndex + ".json";
let filePath = bot.filePathRoot + "/Output/" + bot.process;
if (FULL_LOG === true) { logger.write("[INFO] saveThemAll -> writeExucutionHistory -> fileName = " + fileName); }
@@ -586,8 +639,8 @@
/* Here we will write the file containing the max sequence number. */
- fileContent = thisObject.statusReport.runIndex;
- fileName = "Execution.History." + thisObject.statusReport.runType + "." + "Sequence" + ".json";
+ fileContent = runIndex;
+ fileName = "Execution.History." + bot.runMode + "." + "Sequence" + ".json";
filePath = bot.filePathRoot + "/Output/" + bot.process;
cloudStorage.createTextFile(filePath, fileName, fileContent + '\n', onSequenceFileCreated);
diff --git a/Datasource.js b/Datasource.js
deleted file mode 100644
index 8fdd9dbc0..000000000
--- a/Datasource.js
+++ /dev/null
@@ -1,526 +0,0 @@
-exports.newDatasource = function newDatasource(BOT, DEBUG_MODULE, BLOB_STORAGE, UTILITIES) {
-
- const FULL_LOG = true;
-
- /*
-
- This module allows trading bots to access information stored at the cloud storage.
-
- */
-
- const MODULE_NAME = "Datasource";
-
- let thisObject = {
- initialize: initialize,
- candlesFiles: new Map, // Complete sets of candles for different Time Periods. For Time Periods < 1hs sets are of current day only, otherwise whole market.
- candlesMap: new Map, // The last 10 candles for each Time Period will be stored here.
- stairsFiles: new Map, // Complete sets of patterns for different Time Periods. For Time Periods < 1hs sets are of current day only, otherwise whole market.
- stairsMap: new Map // The patterns we are currently in will be stored here.
- };
-
- let bot = BOT;
-
- const logger = DEBUG_MODULE.newDebugLog();
- logger.fileName = MODULE_NAME;
- logger.bot = bot;
-
- let oliviaStorage = BLOB_STORAGE.newBlobStorage(bot);
- let tomStorage = BLOB_STORAGE.newBlobStorage(bot);
-
- /* Utilities needed. */
-
- let utilities = UTILITIES.newUtilities(bot);
-
- return thisObject;
-
- function initialize(callBackFunction) {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> Entering function."); }
-
- initializeOliviaStorage();
-
- function initializeOliviaStorage() {
-
- if (FULL_LOG === true) { logger.write("[INFO] initializeOliviaStorage -> Entering function."); }
-
- oliviaStorage.initialize({ bot: "AAOlivia", devTeam: "AAMasters" }, onInizialized);
-
- function onInizialized(err) {
- if (err.result === global.DEFAULT_OK_RESPONSE.result) {
- initializeTomStorage();
- } else {
- logger.write("[ERROR] initialize -> initializeOliviaStorage -> err = " + err.message);
- callBackFunction(err);
- }
- }
- }
-
- function initializeTomStorage() {
-
- if (FULL_LOG === true) { logger.write("[INFO] initializeTomStorage -> Entering function."); }
-
- tomStorage.initialize({ bot: "AATom", devTeam: "AAMasters" }, onInizialized);
-
- function onInizialized(err) {
- if (err.result === global.DEFAULT_OK_RESPONSE.result) {
- getCandles(onDone);
- } else {
- logger.write("[ERROR] initialize -> initializeTomStorage -> err = " + err.message);
- callBackFunction(err);
- }
- }
- }
-
- function onDone(err) {
- try {
-
- switch (err.result) {
- case global.DEFAULT_OK_RESPONSE.result: {
- logger.write("[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("[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("[ERROR] initialize -> onDone -> Operation Failed. Aborting the process.");
- callBackFunction(err);
- return;
- }
- }
-
- } catch (err) {
- logger.write("[ERROR] initialize -> onDone -> err = " + err.message);
- callBackFunction(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- function getCandles(callBack) {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getCandles -> Entering function."); }
-
- /*
-
- We will read several files with candles for the current day. We will use these files as an input
- to make trading decitions later.
-
- */
-
- getMarketFiles();
-
- function getMarketFiles() {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getCandles -> getMarketFiles -> Entering function."); }
-
- let filesOk = 0;
- let filesNotOk = 0;
-
- for (i = 0; i < global.marketFilesPeriods.length; i++) {
-
- let periodTime = global.marketFilesPeriods[i][0];
- let periodName = global.marketFilesPeriods[i][1];
-
- getFile(oliviaStorage, "@AssetA_@AssetB.json", "@Exchange/Output/Candles/Multi-Period-Market/@Period", periodName, undefined, onFileReceived, callBack);
-
- function onFileReceived(err, file) {
-
- if (err.result === global.DEFAULT_OK_RESPONSE.result) {
- filesOk++;
- thisObject.candlesFiles.set(periodName, file);
- } else {
- filesNotOk++;
- }
-
- if (filesOk + filesNotOk === global.marketFilesPeriods.length) {
-
- if (filesOk === global.marketFilesPeriods.length) {
-
- getDailyFiles();
-
- } else {
- logger.write("[ERROR] getCandles -> getMarketFiles -> onFileReceived -> Some files are missing -> filesNotOk = " + filesNotOk);
- logger.write("[ERROR] getCandles -> getMarketFiles -> onFileReceived -> Will abort the process and request a retry.");
- callBack(global.DEFAULT_RETRY_RESPONSE);
- return;
- }
- }
- }
- }
- } catch (err) {
- logger.write("[ERROR] getCandles -> getMarketFiles -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- function getDailyFiles() {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getCandles -> getDailyFiles -> Entering function."); }
-
- let filesOk = 0;
- let filesNotOk = 0;
-
- for (i = 0; i < global.dailyFilePeriods.length; i++) {
-
- let periodTime = global.dailyFilePeriods[i][0];
- let periodName = global.dailyFilePeriods[i][1];
-
- getFile(oliviaStorage, "@AssetA_@AssetB.json", "@Exchange/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day", periodName, bot.processDatetime, onFileReceived, callBack);
-
- function onFileReceived(err, file) {
-
- if (err.result === global.DEFAULT_OK_RESPONSE.result) {
- filesOk++;
- thisObject.candlesFiles.set(periodName, file);
- } else {
- filesNotOk++;
- }
-
- if (filesOk + filesNotOk === global.dailyFilePeriods.length) {
-
- if (filesOk === global.dailyFilePeriods.length) {
-
- getCandlesWeAreIn();
-
- } else {
- logger.write("[ERROR] getCandles -> getDailyFiles -> onFileReceived -> Some files are missing -> filesNotOk = " + filesNotOk);
- logger.write("[ERROR] getCandles -> getDailyFiles -> onFileReceived -> Will abort the process and request a retry.");
- callBack(global.DEFAULT_RETRY_RESPONSE);
- return;
- }
- }
- }
- }
- } catch (err) {
- logger.write("[ERROR] getCandles -> getDailyFiles -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- function getCandlesWeAreIn() {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getCandles -> getCandlesWeAreIn -> Entering function."); }
-
- let counter = 0;
-
- thisObject.candlesFiles.forEach(getCurrentCandles);
-
- function getCurrentCandles(pCandlesFile, pPeriodName, map) {
-
- let candlesArray = [];
-
- for (i = 0; i < pCandlesFile.length; i++) {
-
- let candle = {
- open: undefined,
- close: undefined,
- min: 10000000000000,
- max: 0,
- begin: undefined,
- end: undefined,
- direction: undefined
- };
-
- candle.min = pCandlesFile[i][0];
- candle.max = pCandlesFile[i][1];
-
- candle.open = pCandlesFile[i][2];
- candle.close = pCandlesFile[i][3];
-
- candle.begin = pCandlesFile[i][4];
- candle.end = pCandlesFile[i][5];
-
- if (candle.open > candle.close) { candle.direction = 'down'; }
- if (candle.open < candle.close) { candle.direction = 'up'; }
- if (candle.open === candle.close) { candle.direction = 'side'; }
-
- /* We are going to store the last 10 candles per period, which will give the bot a good sense of where it is. */
-
- let timePeriod = candle.end - candle.begin + 1; // In miliseconds. (remember each candle spans a period minus one milisecond)
-
- if (candle.begin >= bot.processDatetime.valueOf() - timePeriod * 10 && candle.begin <= bot.processDatetime.valueOf()) {
-
- candlesArray.push(candle);
-
- }
- }
-
- thisObject.candlesMap.set(pPeriodName, candlesArray);
-
- counter++;
-
- if (counter === thisObject.candlesFiles.size) {
-
- getPatterns(callBack);
-
- }
- }
- } catch (err) {
- logger.write("[ERROR] getCandles -> getCandlesWeAreIn -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- } catch (err) {
- logger.write("[ERROR] getCandles -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- function getPatterns(callBack) {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getPatterns -> Entering function."); }
-
- /*
-
- We will read several files with pattern calculations for the current day. We will use these files as an input
- to make trading decitions later.
-
- */
-
- getMarketFiles();
-
- function getMarketFiles() {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getPatterns -> getMarketFiles -> Entering function."); }
-
- let filesOk = 0;
- let filesNotOk = 0;
-
- for (i = 0; i < global.marketFilesPeriods.length; i++) {
-
- let periodTime = global.marketFilesPeriods[i][0];
- let periodName = global.marketFilesPeriods[i][1];
-
- getFile(tomStorage, "@AssetA_@AssetB.json", "@Exchange/Tom/dataSet.V1/Output/Candle-Stairs/Multi-Period-Market/@Period", periodName, undefined, onFileReceived, callBack);
-
- function onFileReceived(err, file) {
-
- if (err.result === global.DEFAULT_OK_RESPONSE.result) {
- filesOk++;
- thisObject.stairsFiles.set(periodName, file);
- } else {
- filesNotOk++;
- }
-
- if (filesOk + filesNotOk === global.marketFilesPeriods.length) {
-
- if (filesOk === global.marketFilesPeriods.length) {
-
- getDailyFiles();
-
- } else {
- logger.write("[ERROR] getPatterns -> getMarketFiles -> onFileReceived -> Some files are missing -> filesNotOk = " + filesNotOk);
- logger.write("[ERROR] getPatterns -> getMarketFiles -> onFileReceived -> Will abort the process and request a retry.");
- callBack(global.DEFAULT_RETRY_RESPONSE);
- return;
- }
- }
- }
- }
- } catch (err) {
- logger.write("[ERROR] getPatterns -> getMarketFiles -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- function getDailyFiles() {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getPatterns -> getDailyFiles -> Entering function."); }
-
- let filesOk = 0;
- let filesNotOk = 0;
-
- for (i = 0; i < global.dailyFilePeriods.length; i++) {
-
- let periodTime = global.dailyFilePeriods[i][0];
- let periodName = global.dailyFilePeriods[i][1];
-
- getFile(tomStorage, "@AssetA_@AssetB.json", "@Exchange/Tom/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day", periodName, bot.processDatetime, onFileReceived, callBack);
-
- function onFileReceived(err, file) {
-
- if (err.result === global.DEFAULT_OK_RESPONSE.result) {
- filesOk++;
- thisObject.stairsFiles.set(periodName, file);
- } else {
- filesNotOk++;
- }
-
- if (filesOk + filesNotOk === global.dailyFilePeriods.length) {
-
- if (filesOk === global.dailyFilePeriods.length) {
-
- getStairsWeAreIn();
-
- } else {
- logger.write("[ERROR] getPatterns -> getDailyFiles -> onFileReceived -> Some files are missing -> filesNotOk = " + filesNotOk);
- logger.write("[ERROR] getPatterns -> getDailyFiles -> onFileReceived -> Will abort the process and request a retry.");
- callBack(global.DEFAULT_RETRY_RESPONSE);
- return;
- }
- }
- }
- }
- } catch (err) {
- logger.write("[ERROR] getPatterns -> getDailyFiles -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- function getStairsWeAreIn() {
-
- try {
-
- if (FULL_LOG === true) { logger.write("[INFO] getPatterns -> getStairsWeAreIn -> Entering function."); }
-
- let counter = 0;
-
- thisObject.stairsFiles.forEach(getCurrentStairs);
-
- function getCurrentStairs(pStairsFile, pPeriodName, map) {
-
- for (i = 0; i < pStairsFile.length; i++) {
-
- let stairs = {
- open: undefined,
- close: undefined,
- min: 10000000000000,
- max: 0,
- begin: undefined,
- end: undefined,
- direction: undefined,
- candleCount: 0,
- firstMin: 0,
- firstMax: 0,
- lastMin: 0,
- lastMax: 0
- };
-
- stairs.open = pStairsFile[i][0];
- stairs.close = pStairsFile[i][1];
-
- stairs.min = pStairsFile[i][2];
- stairs.max = pStairsFile[i][3];
-
- stairs.begin = pStairsFile[i][4];
- stairs.end = pStairsFile[i][5];
-
- stairs.direction = pStairsFile[i][6];
- stairs.candleCount = pStairsFile[i][7];
-
- stairs.firstMin = pStairsFile[i][8];
- stairs.firstMax = pStairsFile[i][9];
-
- stairs.lastMin = pStairsFile[i][10];
- stairs.lastMax = pStairsFile[i][11];
-
- if (bot.processDatetime.valueOf() >= stairs.begin && bot.processDatetime.valueOf() <= stairs.end) {
-
- thisObject.stairsMap.set(pPeriodName, stairs);
-
- }
- }
-
- counter++;
-
- if (counter === thisObject.stairsFiles.size) {
-
- callBack(global.DEFAULT_OK_RESPONSE);
-
- }
- }
- } catch (err) {
- logger.write("[ERROR] getPatterns -> getStairsWeAreIn -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- } catch (err) {
- logger.write("[ERROR] getPatterns -> err = " + err.message);
- callBack(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-
- function getFile(pFileStorage, pFileName, pFilePath, pPeriodName, pDatetime, innerCallBack, outerCallBack) {
-
- try {
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> Entering function."); }
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> pFileName = " + pFileName); }
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> pFilePath = " + pFilePath); }
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> pPeriodName = " + pPeriodName); }
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> pDatetime = " + pDatetime); }
-
- pFileName = pFileName.replace("@AssetA", MARKET.assetA);
- pFileName = pFileName.replace("@AssetB", MARKET.assetB);
-
- pFilePath = pFilePath.replace("@Exchange", global.EXCHANGE_NAME);
- pFilePath = pFilePath.replace("@Period", pPeriodName);
-
- if (pDatetime !== undefined) {
-
- pFilePath = pFilePath.replace("@Year", pDatetime.getUTCFullYear());
- pFilePath = pFilePath.replace("@Month", utilities.pad(pDatetime.getUTCMonth() + 1, 2));
- pFilePath = pFilePath.replace("@Day", utilities.pad(pDatetime.getUTCDate(), 2));
-
- }
-
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> final pFilePath = " + pFilePath); }
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> final pFileName = " + pFileName); }
-
- pFileStorage.getTextFile(pFilePath, pFileName, onFileReceived);
-
- function onFileReceived(err, text) {
-
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> onFileReceived -> pFilePath = " + pFilePath); }
- if (FULL_LOG === true) { logger.write("[INFO] initialize -> getFile -> onFileReceived -> pFileName = " + pFileName); }
-
- if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
- logger.write("[ERROR] initialize -> getFile -> onFileReceived -> err = " + err.message);
- innerCallBack(err);
- return;
- }
-
- try {
-
- let data = JSON.parse(text);
- innerCallBack(global.DEFAULT_OK_RESPONSE, data);
-
- } catch (err) {
- logger.write("[ERROR] initialize -> getFile -> onFileReceived -> Parsing JSON -> err = " + err.message);
- innerCallBack(err);
- return;
- }
- }
-
- } catch (err) {
- logger.write("[ERROR] initialize -> getFile -> err = " + err.message);
- outerCallBack("Operation Failed");
- }
- }
-
- } catch (err) {
-
- logger.write("[ERROR] initialize -> err = " + err.message);
- callBackFunction(global.DEFAULT_FAIL_RESPONSE);
- }
- }
-};
\ No newline at end of file
diff --git a/Project.njsproj b/Project.njsproj
index a798d6c02..3313fa7bd 100644
--- a/Project.njsproj
+++ b/Project.njsproj
@@ -42,9 +42,6 @@
Code
-
- Code
-
Code
diff --git a/Run.js b/Run.js
index 838dd60f1..a4779b6ea 100644
--- a/Run.js
+++ b/Run.js
@@ -298,9 +298,8 @@ for (let p = 0; p < global.PLATFORM_CONFIG.executionList.length; p++) {
runIndicatorBot(botConfig, processConfig, month, year);
break;
}
- case 'Trading': {
- runTradingBot(botConfig, processConfig);
- break;
+ default: {
+ logger.write("[ERROR] run -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
}
}
@@ -321,23 +320,23 @@ for (let p = 0; p < global.PLATFORM_CONFIG.executionList.length; p++) {
runExtractionBot(botConfig, processConfig, month, year);
break;
}
+ default: {
+ logger.write("[ERROR] run -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
+ }
}
}
}
- if (processConfig.startMode.timePeriod !== undefined) {
+ if (processConfig.startMode.live !== undefined) {
- if (processConfig.startMode.timePeriod.run === "true") {
+ if (processConfig.startMode.live.run === "true") {
- botConfig.backTestingMode = true;
- botConfig.timePeriod = processConfig.startMode.timePeriod;
+ botConfig.runMode = "Live";
- /* We override these waitTimes to the one specified at the timePeriod configuration. */
+ let month = pad((new Date()).getUTCMonth() + 1, 2);
+ let year = (new Date()).getUTCFullYear();
- processConfig.normalWaitTime = processConfig.startMode.timePeriod.waitTime;
- processConfig.retryWaitTime = processConfig.startMode.timePeriod.waitTime;
-
- if (processConfig.startMode.timePeriod.resumeExecution === "true") {
+ if (processConfig.startMode.live.resumeExecution === "true") {
botConfig.hasTheBotJustStarted = false;
} else {
botConfig.hasTheBotJustStarted = true;
@@ -348,6 +347,62 @@ for (let p = 0; p < global.PLATFORM_CONFIG.executionList.length; p++) {
runTradingBot(botConfig, processConfig);
break;
}
+ default: {
+ logger.write("[ERROR] run -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
+ }
+ }
+ }
+ }
+
+ if (processConfig.startMode.backtest !== undefined) {
+
+ if (processConfig.startMode.backtest.run === "true") {
+
+ botConfig.runMode = "Backtest";
+ botConfig.backtest = processConfig.startMode.backtest;
+
+ /* We override these waitTimes to the one specified at the backtest configuration. */
+
+ processConfig.normalWaitTime = processConfig.startMode.backtest.waitTime;
+ processConfig.retryWaitTime = processConfig.startMode.backtest.waitTime;
+
+ /* Backtest Mode does not support Resume Execution, so this is the only way. */
+
+ botConfig.hasTheBotJustStarted = true;
+
+ switch (botConfig.type) {
+ case 'Trading': {
+ runTradingBot(botConfig, processConfig);
+ break;
+ }
+ default: {
+ logger.write("[ERROR] run -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
+ }
+ }
+ }
+ }
+
+ if (processConfig.startMode.competition !== undefined) {
+
+ if (processConfig.startMode.competition.run === "true") {
+
+ botConfig.runMode = "Competition";
+ botConfig.competition = processConfig.startMode.competition;
+
+ if (processConfig.startMode.competition.resumeExecution === "true") {
+ botConfig.hasTheBotJustStarted = false;
+ } else {
+ botConfig.hasTheBotJustStarted = true;
+ }
+
+ switch (botConfig.type) {
+ case 'Trading': {
+ runTradingBot(botConfig, processConfig);
+ break;
+ }
+ default: {
+ logger.write("[ERROR] run -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
+ }
}
}
}
diff --git a/Trading Bot Process Main Loop.js b/Trading Bot Process Main Loop.js
index 4ed118198..ba40a44b7 100644
--- a/Trading Bot Process Main Loop.js
+++ b/Trading Bot Process Main Loop.js
@@ -68,7 +68,6 @@
const POLONIEX_CLIENT_MODULE = require(ROOT_DIR + 'Poloniex API Client');
const EXCHANGE_API = require(ROOT_DIR + 'ExchangeAPI');
const CONTEXT = require(ROOT_DIR + 'Context');
- const DATASOURCE = require(ROOT_DIR + 'Datasource');
const ASSISTANT = require(ROOT_DIR + 'Assistant');
const STATUS_REPORT = require(ROOT_DIR + 'Status Report');
const DATA_SET = require(ROOT_DIR + 'Data Set');
@@ -77,48 +76,83 @@
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
- if (bot.backTestingMode === true) {
+ switch (bot.runMode) {
+ case 'Live': {
- if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Backtesting Mode detected."); }
+ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Live Mode detected."); }
- if (bot.hasTheBotJustStarted === true) {
+ // This will be considered the process date and time, so as to have it consistenly all over the execution.
- if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Bot just starting, setting initial datetime."); }
+ let localDate = new Date();
- bot.processDatetime = new Date(bot.timePeriod.beginDatetime); // Set the starting time as the configured beginDatetime.
-
- } else {
-
- bot.processDatetime = new Date(bot.processDatetime.valueOf() + 60000); // We advance one minute in time.
-
- let endDatetime = new Date(bot.timePeriod.endDatetime);
-
- if (bot.processDatetime.valueOf() > endDatetime.valueOf()) {
-
- if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> End of Backtesting Period reached. Exiting Bot Process Loop."); }
-
- callBackFunction(global.DEFAULT_OK_RESPONSE);
- return;
- }
+ bot.processDatetime = new Date(Date.UTC(
+ localDate.getUTCFullYear(),
+ localDate.getUTCMonth(),
+ localDate.getUTCDate(),
+ localDate.getUTCHours(),
+ localDate.getUTCMinutes(),
+ localDate.getUTCSeconds(),
+ localDate.getUTCMilliseconds()));
+ break;
}
+ case 'Backtest': {
- } else { // We are running Live!
+ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Backtesting Mode detected."); }
- if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Live Mode detected."); }
+ if (bot.hasTheBotJustStarted === true) {
- // This will be considered the process date and time, so as to have it consistenly all over the execution.
+ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Bot just starting, setting initial datetime."); }
- let localDate = new Date();
+ bot.processDatetime = new Date(bot.backtest.beginDatetime); // Set the starting time as the configured beginDatetime.
- bot.processDatetime = new Date(Date.UTC(
- localDate.getUTCFullYear(),
- localDate.getUTCMonth(),
- localDate.getUTCDate(),
- localDate.getUTCHours(),
- localDate.getUTCMinutes(),
- localDate.getUTCSeconds(),
- localDate.getUTCMilliseconds()));
+ } else {
+ bot.processDatetime = new Date(bot.processDatetime.valueOf() + 60000); // We advance one minute in time.
+
+ let endDatetime = new Date(bot.backtest.endDatetime);
+
+ if (bot.processDatetime.valueOf() > endDatetime.valueOf()) {
+
+ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> End of Backtesting Period reached. Exiting Bot Process Loop."); }
+
+ callBackFunction(global.DEFAULT_OK_RESPONSE);
+ return;
+ }
+ }
+ break;
+ }
+ case 'Competition': {
+
+ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Competition Mode detected."); }
+
+ if (bot.hasTheBotJustStarted === true) {
+
+ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Bot just starting, setting initial datetime."); }
+
+ bot.processDatetime = new Date(bot.competition.beginDatetime); // Set the starting time as the configured beginDatetime.
+
+ } else {
+
+ bot.processDatetime = new Date(bot.processDatetime.valueOf() + 60000); // We advance one minute in time.
+
+ let endDatetime = new Date(bot.competition.endDatetime);
+
+ if (bot.processDatetime.valueOf() > endDatetime.valueOf()) {
+
+ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> End of Competition Period reached. Exiting Bot Process Loop."); }
+
+ callBackFunction(global.DEFAULT_OK_RESPONSE);
+ return;
+ }
+ }
+ break;
+ }
+ default: {
+ logger.write("[ERROR] run -> loop -> Unexpected bot.runMode.");
+ logger.write("[ERROR] run -> loop -> bot.runMode = " + bot.runMode);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ return;
+ }
}
if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> bot.processDatetime = " + bot.processDatetime); }