diff --git a/.vs/AACloud/v15/.suo b/.vs/AACloud/v15/.suo index aebf99793..8411265a3 100644 Binary files a/.vs/AACloud/v15/.suo and b/.vs/AACloud/v15/.suo differ diff --git a/Assistant.js b/Assistant.js index 09f77ba0f..90c2f40e7 100644 --- a/Assistant.js +++ b/Assistant.js @@ -115,9 +115,9 @@ /* If we are in Exchange Simulation Mode then there is not much to do here. */ - if (global.EXCHANGE_SIMULATION_MODE === true) { + if (bot.backTesting === true) { - logger.write("[WARN] initialize -> Exchange Simulation Mode detected. -> Skipping all validations."); + logger.write("[WARN] initialize -> Backtesting Mode detected. -> Skipping validateExchangeSyncronicity."); callBackFunction(global.DEFAULT_OK_RESPONSE); return; @@ -683,15 +683,16 @@ /* All validations passed, we proceed. */ - if (global.EXCHANGE_SIMULATION_MODE === false) { - - exchangeAPI.putPosition(global.MARKET, pType, pRate, pAmountA, pAmountB, onResponse); - - } else { + if (bot.backTesting === true) { 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); + + } else { + + exchangeAPI.putPosition(global.MARKET, pType, pRate, pAmountA, pAmountB, onResponse); + } function onResponse(err, pPositionId) { @@ -775,15 +776,16 @@ if (FULL_LOG === true) { logger.write("[INFO] movePosition -> pPosition = " + JSON.stringify(pPosition)); } if (FULL_LOG === true) { logger.write("[INFO] movePosition -> pNewRate = " + pNewRate); } - if (global.EXCHANGE_SIMULATION_MODE === false) { - - exchangeAPI.movePosition(pPosition, pNewRate, onResponse); - - } else { + if (bot.backTesting === true) { 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); + + } else { + + exchangeAPI.movePosition(pPosition, pNewRate, onResponse); + } function onResponse(err, pPositionId) { diff --git a/Context.js b/Context.js index fc42f878b..0c90ce503 100644 --- a/Context.js +++ b/Context.js @@ -121,6 +121,9 @@ switch (err.result) { case global.DEFAULT_OK_RESPONSE.result: { logger.write("[INFO] initialize -> onDone -> Execution finished well. :-)"); + + bot.hasTheBotJustStarted = false; + callBackFunction(global.DEFAULT_OK_RESPONSE); return; } @@ -157,13 +160,14 @@ statusReportModule = statusDependencies.statusReports.get(key); thisObject.statusReport = statusReportModule.file; - if (thisObject.statusReport.lastExecution !== undefined) { + if (bot.hasTheBotJustStarted === true) { - getExecutionHistory(callBack); // Happens when the Status Report exists. + createConext(callBack); } else { - createConext(callBack); // Happens when the Status Report does NOT exists. + getExecutionHistory(callBack); + } } catch (err) { @@ -178,7 +182,7 @@ if (FULL_LOG === true) { logger.write("[INFO] initialize -> getExecutionHistory -> Entering function."); } - let fileName = "Execution.History.json"; + let fileName = "Execution.History." + thisObject.statusReport.runType + "." + thisObject.statusReport.runIndex + ".json"; let filePath = bot.filePathRoot + "/Output/" + bot.process; if (FULL_LOG === true) { logger.write("[INFO] initialize -> getExecutionHistory -> fileName = " + fileName); } @@ -238,7 +242,7 @@ let date = new Date(thisObject.statusReport.lastExecution); - let fileName = "Execution.Context.json"; + let fileName = "Execution.Context." + thisObject.statusReport.runType + "." + thisObject.statusReport.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; @@ -306,7 +310,47 @@ */ - thisObject.statusReport = {}; + let runType; + + if (bot.backTesting === 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. + + thisObject.statusReport = { + runType: runType, + runIndex: 0, + liveRuns: [], + backtestRuns: [] + }; + + } else { // The Status Report does exist, we just need to move to the next runIndex. + + thisObject.statusReport.runType = runType; + let runContent = { + lastExecution: bot.processDatetime + }; + + switch (runType) { + + case "Backtest": { + thisObject.statusReport.backtestRuns.push(runContent); + thisObject.statusReport.runIndex = thisObject.statusReport.backtestRuns.lenght - 1; + break; + } + + case "Live": { + thisObject.statusReport.liveRuns.push(runContent); + thisObject.statusReport.runIndex = thisObject.statusReport.liveRuns.lenght - 1; + break; + } + } + } thisObject.executionHistory = []; @@ -398,7 +442,7 @@ if (FULL_LOG === true) { logger.write("[INFO] saveThemAll -> writeExecutionContext -> Entering function."); } - let fileName = "Execution.Context.json"; + let fileName = "Execution.Context." + thisObject.statusReport.runType + "." + thisObject.statusReport.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; @@ -459,7 +503,7 @@ if (FULL_LOG === true) { logger.write("[INFO] saveThemAll -> writeExucutionHistory -> Entering function."); } - let fileName = "Execution.History.json"; + let fileName = "Execution.History." + thisObject.statusReport.runType + "." + thisObject.statusReport.runIndex + ".json"; let filePath = bot.filePathRoot + "/Output/" + bot.process; if (FULL_LOG === true) { logger.write("[INFO] saveThemAll -> writeExucutionHistory -> fileName = " + fileName); } @@ -535,7 +579,6 @@ if (FULL_LOG === true) { logger.write("[INFO] saveThemAll -> writeStatusReport -> Entering function."); } - statusReportModule.file.lastExecution = bot.processDatetime; statusReportModule.save(callBack); } diff --git a/Run.js b/Run.js index a3920f4f9..735db9fc4 100644 --- a/Run.js +++ b/Run.js @@ -17,10 +17,6 @@ catch (err) { return; } -/* You do not have funds at the exchange and still want run your bot? No problem activate the exchange simulation mode: */ - -global.EXCHANGE_SIMULATION_MODE = JSON.parse(global.PLATFORM_CONFIG.exchangeSimulationMode); - /* The following global variable tells the system if it is running on test mode or production. */ global.STORAGE_CONN_STRING_FOLDER = global.PLATFORM_CONFIG.storageConnStringFolder; // 'Testnet', 'Mixed' or 'Production', or whatever folder name the conn strings files are into. @@ -319,10 +315,24 @@ for (let p = 0; p < global.PLATFORM_CONFIG.executionList.length; p++) { runExtractionBot(botConfig, processConfig, month, year); break; } - case 'Indicator': { - runIndicatorBot(botConfig, processConfig, month, year); - break; - } + } + } + } + + if (processConfig.startMode.timePeriod !== undefined) { + + if (processConfig.startMode.timePeriod.run === "true") { + + botConfig.backTesting = true; + botConfig.hasTheBotJustStarted = true; + botConfig.timePeriod = processConfig.startMode.timePeriod; + + /* We override these waitTimes to the one specified at the timePeriod configuration. */ + + processConfig.normalWaitTime = processConfig.startMode.timePeriod.waitTime; + processConfig.retryWaitTime = processConfig.startMode.timePeriod.waitTime; + + switch (botConfig.type) { case 'Trading': { runTradingBot(botConfig, processConfig); break; diff --git a/Trading Bot Process Main Loop.js b/Trading Bot Process Main Loop.js index e7fabb498..124dfa0de 100644 --- a/Trading Bot Process Main Loop.js +++ b/Trading Bot Process Main Loop.js @@ -66,7 +66,7 @@ const BLOB_STORAGE = require(ROOT_DIR + 'Blob Storage'); const DEBUG_MODULE = require(ROOT_DIR + 'Debug Log'); const POLONIEX_CLIENT_MODULE = require(ROOT_DIR + 'Poloniex API Client'); - const EXCHANGE_API = require(ROOT_DIR + 'ExchangeAPI'); + const EXCHANGE_API = require(ROOT_DIR + 'RealExchangeAPI'); const CONTEXT = require(ROOT_DIR + 'Context'); const DATASOURCE = require(ROOT_DIR + 'Datasource'); const ASSISTANT = require(ROOT_DIR + 'Assistant'); @@ -77,8 +77,41 @@ /* 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. */ - bot.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution. + if (bot.backTesting === true) { + if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Backtesting 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.timePeriod.beginDatetime); // Set the starting time as the configured beginDatetime. + + let endDatetime = new Date(bot.timePeriod.beginDatetime); + + 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; + } + + } else { + + bot.processDatetime = new Date(bot.processDatetime.valueOf() + 60000); // We advance one minute in time. + } + + } else { // We are running Live! + + if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> Live Mode detected."); } + + bot.processDatetime = new Date(); // 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.processDatetime = " + bot.processDatetime); } + /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ let context; @@ -210,6 +243,7 @@ if (FULL_LOG === true) { logger.write("[INFO] run -> loop -> initializeExchangeAPI -> Entering function."); } exchangeAPI = EXCHANGE_API.newExchangeAPI(bot, DEBUG_MODULE, POLONIEX_CLIENT_MODULE); + exchangeAPI.initialize(onInizialized); function onInizialized(err) { diff --git a/this.config.json b/this.config.json index 87d26b9af..ca677d9db 100644 --- a/this.config.json +++ b/this.config.json @@ -43,7 +43,6 @@ } ], "stopGracefully": "false", - "exchangeSimulationMode": "false", "storageConnStringFolder": "Production", "maxLogLoops": 5, "marketRateProvider": {