diff --git a/Context.js b/Context.js index 9fceb3106..62d3842a7 100644 --- a/Context.js +++ b/Context.js @@ -70,15 +70,18 @@ let runIndex; // This is the index for this run and depends on the startMode. + let totalAlgobots; + return thisObject; - function initialize(pStatusDependencies, callBackFunction) { + function initialize(pStatusDependencies, pTotalAlgobots, callBackFunction) { try { if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } statusDependencies = pStatusDependencies; + totalAlgobots = pTotalAlgobots; /* @@ -114,8 +117,6 @@ case global.DEFAULT_OK_RESPONSE.result: { if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> onDone -> Execution finished well."); } - bot.hasTheBotJustStarted = false; - callBackFunction(global.DEFAULT_OK_RESPONSE); return; } @@ -328,8 +329,8 @@ once we advance into multiple competitions scheme. */ - const INITIAL_INVESTMENT_A = 0; // This is just for this release of the platform. - const INITIAL_INVESTMENT_B = .001; // This is just for this release of the platform. + const INITIAL_INVESTMENT_A = 0; // This is just for this release of the platform. + const INITIAL_INVESTMENT_B = .001 / totalAlgobots; // This is just for this release of the platform. thisObject.executionContext = { investment: { // This is used to calculate profits. @@ -384,6 +385,9 @@ 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; } diff --git a/PoloniexAPIClient.js b/PoloniexAPIClient.js index fa378f521..bc6ce916e 100644 --- a/PoloniexAPIClient.js +++ b/PoloniexAPIClient.js @@ -18,8 +18,7 @@ // Module dependencies var crypto = require('crypto'), - request = require('request'), - nonce = require('nonce')(); + request = require('request'); // Constants var version = '0.0.8', @@ -122,7 +121,7 @@ parameters || (parameters = {}); parameters.command = command; - parameters.nonce = nonce(); + parameters.nonce = global.nonce(); options = { method: 'POST', diff --git a/Root.js b/Root.js index cf2dd5839..696fa6251 100644 --- a/Root.js +++ b/Root.js @@ -386,7 +386,7 @@ exports.newRoot = function newRoot() { } - /* We tesst each type of start Mode to get what to run and how. */ + /* We test each type of start Mode to get what to run and how. */ if (processConfig.startMode.allMonths !== undefined) { @@ -756,57 +756,157 @@ exports.newRoot = function newRoot() { function runTradingBot(pBotConfig, pProcessConfig) { try { - const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); - let logger; - logger = DEBUG_MODULE.newDebugLog(); - logger.bot = pBotConfig; + if (FULL_LOG === true) { console.log(logDisplace + "[INFO] start -> findProcess -> runTradingBot -> Entering function."); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> Entering function."); } + if (pBotConfig.geneticRules !== undefined) { - let tradingBotMainLoop = TRADING_BOT_MAIN_LOOP_MODULE.newTradingBotProcessMainLoop(pBotConfig, logger); - tradingBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); + /* Here, based on the genetic rules we will create one instance for each combination of genes */ - function onInitializeReady(err) { + let valueMatrix = []; - if (err.result === global.DEFAULT_OK_RESPONSE.result) { + for (let i = 0; i < pBotConfig.geneticRules.length; i++) { - tradingBotMainLoop.run(whenRunFinishes); + let rule = pBotConfig.geneticRules[i]; - function whenRunFinishes(err) { + let possibleValues = []; - pBotConfig.loopCounter = 0; + for (let j = rule.lowerLimit; j <= rule.upperLimit; j++) { - let botId; + possibleValues.push(j); - botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.process; + } - if (err.result === global.DEFAULT_OK_RESPONSE.result) { + valueMatrix.push(possibleValues); - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + } - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> botId = " + botId); - console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); - logger.persist(); + /* + Now we have all the possible genes values in a multi-dimensional matrix. + We will go thorugh each of the elements of each dimension and get each combination possible with the other dimmensions. + */ + + let combinations = []; + let combination = []; + let dimensionIndex = 0; + + calculateCombinations(dimensionIndex, combination); + + function calculateCombinations(pDimensionIndex, pCombination) { + + let dimension = valueMatrix[pDimensionIndex]; + + for (let j = 0; j < dimension.length; j++) { + + let copy = JSON.parse(JSON.stringify(pCombination)); + + let value = dimension[j]; + copy.push(value); + + if (pDimensionIndex < valueMatrix.length - 1) { + + calculateCombinations(pDimensionIndex + 1, copy); } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bye."); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); - logger.persist(); + combinations.push(copy); + } } + } - } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> err = " + err.message); - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> Bot will not be started. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> onInitializeReady -> err = " + err.message); + /* At this point we have an array with all the possible combinations, we just need to create an instance for each one and set the genes according to that. */ - logger.persist(); + for (let i = 0; i < combinations.length; i++) { + + let botConfig = JSON.parse(JSON.stringify(pBotConfig)); + let combination = combinations[i]; + let genes = {}; + let clonKey = ""; + + for (let j = 0; j < botConfig.geneticRules.length; j++) { + + genes[botConfig.geneticRules[j].name] = combination[j]; + clonKey = clonKey + "." + combination[j]; + + } + + botConfig.filePathRoot = botConfig.filePathRoot + "/" + "Clon" + clonKey; + botConfig.instance = "Clon" + clonKey; + setTimeout(execute, i * 2 * 1000); + + function execute() { + + createBotInstance(genes, combinations.length, botConfig); + + } + } + } else { + + /* If the bot does not have any genetic rules at all */ + + let genes = {}; + botConfig.instance = "Master"; + + createBotInstance(genes, 1, botConfig); + + } + + + function createBotInstance(pGenes, pTotalInstances, pBotConfig) { + + const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); + let logger; + + logger = DEBUG_MODULE.newDebugLog(); + logger.bot = pBotConfig; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> Entering function."); } + + let tradingBotMainLoop = TRADING_BOT_MAIN_LOOP_MODULE.newTradingBotProcessMainLoop(pBotConfig, logger); + tradingBotMainLoop.initialize(UI_COMMANDS, pProcessConfig, onInitializeReady); + + function onInitializeReady(err) { + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + tradingBotMainLoop.run(pGenes, pTotalInstances, whenRunFinishes); + + function whenRunFinishes(err) { + + pBotConfig.loopCounter = 0; + + let botId; + + botId = pBotConfig.devTeam + "." + pBotConfig.codeName + "." + pBotConfig.instance + "." + pBotConfig.process; + + if (err.result === global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + logger.write(MODULE_NAME, "[INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> botId = " + botId); + console.log(logDisplace + "Root : [INFO] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully."); + logger.persist(); + + } else { + + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bye."); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs."); + logger.persist(); + } + } + + } else { + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = " + err.message); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> Bot will not be started. "); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = " + err.message); + + logger.persist(); + } } } } diff --git a/Run.js b/Run.js index fbfb498a1..ffe8d766f 100644 --- a/Run.js +++ b/Run.js @@ -32,6 +32,8 @@ process.on('exit', function (code) { global.USER_PROFILE = {}; global.EMAIL_CONFIG = {}; +global.nonce = require('nonce')(); // We need a nonce generator that is global so that nonce is generated with a lower number in any case. + readStoragePermissions(); function readStoragePermissions() { diff --git a/StatusReport.js b/StatusReport.js index a736ae325..155f2aaf9 100644 --- a/StatusReport.js +++ b/StatusReport.js @@ -88,10 +88,24 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> load -> Entering function."); } - let rootPath = owner.devTeam + "/" + owner.bot + "." + owner.botVersion.major + "." + owner.botVersion.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + owner.dataSetVersion; let fileName = "Status.Report." + global.MARKET.assetA + '_' + global.MARKET.assetB + ".json"; - let filePath = rootPath + "/Reports/" + owner.process + timePath; - + let filePath; + + let ownerId = owner.devTeam + "-" + owner.bot + "-" + owner.botVersion.major + "-" + owner.botVersion.minor + "-" + owner.process + "-" + owner.dataSetVersion; + let botId = bot.devTeam + "-" + bot.codeName + "-" + bot.version.major + "-" + bot.version.minor + "-" + bot.process + "-" + bot.dataSetVersion; + + if (ownerId !== botId) { + + let rootPath = owner.devTeam + "/" + owner.bot + "." + owner.botVersion.major + "." + owner.botVersion.minor + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + owner.dataSetVersion; + + filePath = rootPath + "/Reports/" + owner.process + timePath; + + } else { + + filePath = bot.filePathRoot + "/Reports/" + owner.process + timePath; + + } + if (bot.type === 'Trading') { fileName = bot.startMode + "." + fileName; } diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index 53d88c752..96c1cdc3c 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -131,7 +131,7 @@ } } - function run(callBackFunction) { + function run(pGenes, pTotalAlgobots, callBackFunction) { try { if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] run -> Entering function."); } @@ -159,7 +159,7 @@ return str.length < max ? pad(" " + str, max) : str; } - console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " Entered into Main Loop # " + pad(Number(bot.loopCounter) + 1, 8)); + console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.instance, 20) + " " + pad(bot.process, 30) + " Entered into Main Loop # " + pad(Number(bot.loopCounter) + 1, 8)); /* For each loop we want to create a new log file. */ @@ -535,7 +535,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeContext -> Entering function."); } context = CONTEXT.newContext(bot, logger, BLOB_STORAGE, UTILITIES, STATUS_REPORT); - context.initialize(statusDependencies, onInizialized); + context.initialize(statusDependencies, pTotalAlgobots, onInizialized); function onInizialized(err) { @@ -756,7 +756,7 @@ usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE); - usertBot.initialize(assistant, onInizialized); + usertBot.initialize(assistant, pGenes, onInizialized); function onInizialized(err) { @@ -1058,7 +1058,7 @@ if (now - bot.loopStartTime > processConfig.normalWaitTime) { logger.write(MODULE_NAME, "[ERROR] run -> loop -> checkLoopHealth -> Dead loop found -> pLastLoop = " + pLastLoop); - console.log((new Date().toISOString() + " [ERROR] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found dead. Resurrecting it now.")); + console.log((new Date().toISOString() + " [ERROR] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.instance, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found dead. Resurrecting it now.")); logger.persist(); // We persist the logs of the failed execution. clearTimeout(nextLoopTimeoutHandle); // We cancel the timeout in case the original loop was still running and schedulled to reexecute. @@ -1066,7 +1066,7 @@ } else { - console.log((new Date().toISOString() + " [WARN] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found delayed but still alive. No action taken.")); + console.log((new Date().toISOString() + " [WARN] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.instance, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found delayed but still alive. No action taken.")); } } diff --git a/package-lock.json b/package-lock.json index 592c336cf..c8ab954bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,13 @@ { "name": "AACloud", "version": "1.0.0", - "lockfileVersion": 1 + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "nodemailer": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.6.7.tgz", + "integrity": "sha512-GIAAYvs9XIP1fBa8wR89ukUh3yjL44pom5LKY5nTZcL+Zp9sRkqL8wgskyBQECQg9CPsDX/fjTZx8MNz20t0jA==" + } + } } diff --git a/package.json b/package.json index 18009b9f7..f9043e400 100644 --- a/package.json +++ b/package.json @@ -8,5 +8,7 @@ }, "author": "Luis-Fernando-Molina", "license": "ISC", - "dependencies": {} + "dependencies": { + "nodemailer": "^4.6.7" + } }