diff --git a/.vs/AACloudPlatform/v15/.suo b/.vs/AACloudPlatform/v15/.suo index f978ceb32..5b165dc5e 100644 Binary files a/.vs/AACloudPlatform/v15/.suo and b/.vs/AACloudPlatform/v15/.suo differ diff --git a/Assistant.js b/Assistant.js index 3237cccd1..00584fab5 100644 --- a/Assistant.js +++ b/Assistant.js @@ -26,7 +26,6 @@ let openPositions = []; // These are the open positions the bot knows it made by itself. let botContext; - let processDatetime; let exchangeAPI; return thisObject; @@ -40,7 +39,6 @@ /* Store local values. */ botContext = pBotContext; - processDatetime = pProcessDatetime; exchangeAPI = pExchangeAPI; getPositionsAtExchange(onDone); @@ -439,7 +437,7 @@ rate: pRate, amountA: pAmountA, amountB: pAmountB, - date: (processDatetime.valueOf()), + date: (global.processDatetime.valueOf()), status: "open", trades: [] }; @@ -501,7 +499,7 @@ rate: pNewRate, amountA: pPosition.amountB * pNewRate, amountB: pPosition.amountB, - date: (processDatetime.valueOf()), + date: (global.processDatetime.valueOf()), status: "open", trades: [] }; diff --git a/Azure File Storage.js b/Azure File Storage.js index 518cf0080..af33c59d8 100644 --- a/Azure File Storage.js +++ b/Azure File Storage.js @@ -45,6 +45,8 @@ exports.newAzureFileStorage = function newAzureFileStorage(BOT) { dataOwner = pDataOwnerBotCodeName; } + logger.fileName = MODULE_NAME + '.' + dataOwner; + readConnectionStringConfigFile(onConnectionStringReady); function onConnectionStringReady(err, pConnObj) { diff --git a/Context.js b/Context.js index 1694892b9..5705fcd62 100644 --- a/Context.js +++ b/Context.js @@ -64,11 +64,9 @@ let cloudStorage = FILE_STORAGE.newAzureFileStorage(bot); - let processDatetime; - return thisObject; - function initialize(pProcessDatetime, callBackFunction) { + function initialize(callBackFunction) { try { @@ -90,8 +88,7 @@ if (err.result === global.DEFAULT_OK_RESPONSE.result) { - thisObject.newHistoryRecord.date = pProcessDatetime; - processDatetime = pProcessDatetime; + thisObject.newHistoryRecord.date = global.processDatetime; getStatusReport(onDone); @@ -372,7 +369,7 @@ try { let fileName = "Execution.Context.json" - let dateForPath = processDatetime.getUTCFullYear() + '/' + utilities.pad(processDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(processDatetime.getUTCDate(), 2) + '/' + utilities.pad(processDatetime.getUTCHours(), 2) + '/' + utilities.pad(processDatetime.getUTCMinutes(), 2); + let dateForPath = global.processDatetime.getUTCFullYear() + '/' + utilities.pad(global.processDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(global.processDatetime.getUTCDate(), 2) + '/' + utilities.pad(global.processDatetime.getUTCHours(), 2) + '/' + utilities.pad(global.processDatetime.getUTCMinutes(), 2); let filePath = bot.devTeam + "/" + bot.codeName + "/" + bot.version + "/" + bot.dataSetVersion + "/Output/" + bot.process + "/" + global.EXCHANGE_NAME + "/" + dateForPath; utilities.createFolderIfNeeded(filePath, cloudStorage, onFolderCreated); @@ -507,7 +504,7 @@ return; } - thisObject.statusReport.lastExecution = processDatetime; + thisObject.statusReport.lastExecution = global.processDatetime; let fileContent = JSON.stringify(thisObject.statusReport); diff --git a/Datasource.js b/Datasource.js index def11fc87..4f2c9b90e 100644 --- a/Datasource.js +++ b/Datasource.js @@ -140,7 +140,9 @@ function getMarketFiles() { try { - /* Now we will get the market files */ + + let filesOk = 0; + let filesNotOk = 0; for (i = 0; i < marketFilesPeriods.length; i++) { @@ -149,14 +151,27 @@ getFile(oliviaAzureFileStorage, "@AssetA_@AssetB.json", "@Exchange/Output/Candles/Multi-Period-Market/@Period", periodName, undefined, onFileReceived, callBack); - function onFileReceived(file) { + function onFileReceived(err, file) { - thisObject.candlesFiles.set(periodName, file); + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + filesOk++; + thisObject.candlesFiles.set(periodName, file); + } else { + filesNotOk++; + } - if (thisObject.candlesFiles.size === marketFilesPeriods.length) { + if (filesOk + filesNotOk === marketFilesPeriods.length) { - getDailyFiles(); + if (filesOk === 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; + } } } } @@ -169,21 +184,38 @@ function getDailyFiles() { try { + + let filesOk = 0; + let filesNotOk = 0; + for (i = 0; i < dailyFilePeriods.length; i++) { let periodTime = dailyFilePeriods[i][0]; let periodName = dailyFilePeriods[i][1]; - getFile(oliviaAzureFileStorage, "@AssetA_@AssetB.json", "@Exchange/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day", periodName, processDatetime, onFileReceived, callBack); + getFile(oliviaAzureFileStorage, "@AssetA_@AssetB.json", "@Exchange/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day", periodName, global.processDatetime, onFileReceived, callBack); - function onFileReceived(file) { + function onFileReceived(err, file) { - thisObject.candlesFiles.set(periodName, file); + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + filesOk++; + thisObject.candlesFiles.set(periodName, file); + } else { + filesNotOk++; + } - if (thisObject.candlesFiles.size === dailyFilePeriods.length + marketFilesPeriods.length) { + if (filesOk + filesNotOk === dailyFilePeriods.length) { - getCandlesWeAreIn(); + if (filesOk === 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; + } } } } @@ -233,7 +265,7 @@ let timePeriod = candle.end - candle.begin + 1; // In miliseconds. (remember each candle spans a period minus one milisecond) - if (candle.begin >= processDatetime.valueOf() - timePeriod * 10 && candle.end <= processDatetime.valueOf()) { + if (candle.begin >= global.processDatetime.valueOf() - timePeriod * 10 && candle.end <= global.processDatetime.valueOf()) { candlesArray.push(candle); @@ -277,7 +309,9 @@ function getMarketFiles() { try { - /* Now we will get the market files */ + + let filesOk = 0; + let filesNotOk = 0; for (i = 0; i < marketFilesPeriods.length; i++) { @@ -286,14 +320,27 @@ getFile(tomAzureFileStorage, "@AssetA_@AssetB.json", "@Exchange/Tom/dataSet.V1/Output/Candle-Stairs/Multi-Period-Market/@Period", periodName, undefined, onFileReceived, callBack); - function onFileReceived(file) { + function onFileReceived(err, file) { - thisObject.stairsFiles.set(periodName, file); + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + filesOk++; + thisObject.stairsFiles.set(periodName, file); + } else { + filesNotOk++; + } - if (thisObject.stairsFiles.size === marketFilesPeriods.length) { + if (filesOk + filesNotOk === marketFilesPeriods.length) { - getDailyFiles(); + if (filesOk === 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; + } } } } @@ -306,21 +353,38 @@ function getDailyFiles() { try { + + let filesOk = 0; + let filesNotOk = 0; + for (i = 0; i < dailyFilePeriods.length; i++) { let periodTime = dailyFilePeriods[i][0]; let periodName = dailyFilePeriods[i][1]; - getFile(tomAzureFileStorage, "@AssetA_@AssetB.json", "@Exchange/Tom/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day", periodName, processDatetime, onFileReceived, callBack); + getFile(tomAzureFileStorage, "@AssetA_@AssetB.json", "@Exchange/Tom/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day", periodName, global.processDatetime, onFileReceived, callBack); - function onFileReceived(file) { + function onFileReceived(err, file) { - thisObject.stairsFiles.set(periodName, file); + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + filesOk++; + thisObject.stairsFiles.set(periodName, file); + } else { + filesNotOk++; + } - if (thisObject.stairsFiles.size === dailyFilePeriods.length + marketFilesPeriods.length) { + if (filesOk + filesNotOk === dailyFilePeriods.length) { - getStairsWeAreIn(); + if (filesOk === 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; + } } } } @@ -374,7 +438,7 @@ stairs.lastMin = pStairsFile[i][10]; stairs.lastMax = pStairsFile[i][11]; - if (processDatetime.valueOf() >= stairs.begin && processDatetime.valueOf() <= stairs.end) { + if (global.processDatetime.valueOf() >= stairs.begin && global.processDatetime.valueOf() <= stairs.end) { thisObject.stairsMap.set(pPeriodName, stairs); @@ -424,24 +488,30 @@ } + 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); - outerCallBack(err); + innerCallBack(err); return; } try { let data = JSON.parse(text); - innerCallBack(data); + innerCallBack(global.DEFAULT_OK_RESPONSE, data); } catch (err) { logger.write("[ERROR] initialize -> getFile -> onFileReceived -> Parsing JSON -> err = " + err.message); - outerCallBack(err); + innerCallBack(err); return; } } diff --git a/Run.js b/Run.js index 7097f8ece..d6c2a999b 100644 --- a/Run.js +++ b/Run.js @@ -3,7 +3,7 @@ const FULL_LOG = true; /* The following global variable tells the system if it is running on test mode or production. */ -global.RUNNING_MODE = 'Testnet'; // or 'Production' +global.RUNNING_MODE = 'Production'; // 'Testnet' or 'Production' /* First thing to do is to read the config and guess which bot we will be running. */ diff --git a/Trading Bot Main Loop.js b/Trading Bot Main Loop.js index 1fe7316b4..cd4c17c86 100644 --- a/Trading Bot Main Loop.js +++ b/Trading Bot Main Loop.js @@ -3,7 +3,7 @@ let bot = BOT; const ROOT_DIR = './'; - const MODULE_NAME = "Trading Bot"; + const MODULE_NAME = "Trading Bot Main Loop"; const FULL_LOG = true; let USER_BOT_MODULE; @@ -63,8 +63,8 @@ /* 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. */ - let processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution. - processDatetime = new Date(processDatetime.valueOf() - 30 * 24 * 60 * 60 * 1000); // we go 30 days back in time since candles are currently not up to date. + global.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution. + global.processDatetime = new Date(global.processDatetime.valueOf() - 30 * 24 * 60 * 60 * 1000); // we go 30 days back in time since candles are currently not up to date. /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ @@ -83,7 +83,7 @@ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> initializeContext -> Entering function."); } context = CONTEXT.newContext(bot, DEBUG_MODULE, AZURE_FILE_STORAGE); - context.initialize(processDatetime, onInizialized); + context.initialize(onInizialized); function onInizialized(err) { @@ -91,7 +91,13 @@ initializeDatasource(); } else { logger.write("[ERROR] run -> loop -> initializeContext -> err = " + err.message); - callBackFunction(err); + if (err.result === global.DEFAULT_RETRY_RESPONSE.result) { + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + } + else { + callBackFunction(err); + } } } } @@ -104,11 +110,12 @@ datasource.initialize(onInizialized); function onInizialized(err) { - - if (err.result === global.DEFAULT_OK_RESPONSE.result) { - initializeExchangeAPI(); - } else { - logger.write("[ERROR] run -> loop -> initializeDatasource -> err = " + err.message); + logger.write("[ERROR] run -> loop -> initializeDatasource -> err = " + err.message); + if (err.result === global.DEFAULT_RETRY_RESPONSE.result) { + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + } + else { callBackFunction(err); } } @@ -137,7 +144,7 @@ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> initializeAssistant -> Entering function."); } assistant = ASSISTANT.newAssistant(bot, DEBUG_MODULE); - assistant.initialize(processDatetime, context, exchangeAPI, onInizialized); + assistant.initialize(context, exchangeAPI, onInizialized); function onInizialized(err) { @@ -159,8 +166,7 @@ let platform = { context: context, datasource: datasource, - assistant: assistant, - processDatetime: processDatetime + assistant: assistant }; usertBot.initialize(platform, onInizialized);