From 5e427ffde3f97e9fc31afda0d49a3191cfd3f154 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Thu, 26 Jul 2018 09:43:26 +0200 Subject: [PATCH 1/9] Exchange Presicion constant added --- Assistant.js | 6 ++++-- ExchangeAPI.js | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Assistant.js b/Assistant.js index 32b181745..9ee69d79a 100644 --- a/Assistant.js +++ b/Assistant.js @@ -557,7 +557,7 @@ if (thisPosition.id === pPositionId) { - let feeRate = 0.0025; // Default fee + let feeRate = 0.002; // Default fee if (Math.random(1) < 0.5) feeRate = 0.0015; // Some times we will pay less fee @@ -737,7 +737,9 @@ sumAssetA = thisObject.truncDecimals(sumAssetA); sumAssetB = thisObject.truncDecimals(sumAssetB); - if (Math.abs(thisObject.truncDecimals(position.amountA) - sumAssetA) > 0.00000001 || Math.abs(position.amountB - sumAssetB) > 0.00000001) { + const EXCHANGE_PRECISION = 0.00001; // This value was determined empirically. We noticed that the sume of the trades plus the remaining order at the exchange didn't exatly matched the positions we keep at the execution context, and the only explanation found was that the exchange presicion was not big enough to make it match. So to avoid unnecesary warnings, we created this constant that filters out this situation. + + if (Math.abs(thisObject.truncDecimals(position.amountA) - sumAssetA) > EXCHANGE_PRECISION || Math.abs(position.amountB - sumAssetB) > EXCHANGE_PRECISION) { logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> position.amountA = " + position.amountA); logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> sumAssetA = " + sumAssetA); diff --git a/ExchangeAPI.js b/ExchangeAPI.js index d3ea64b8a..744c7ac65 100644 --- a/ExchangeAPI.js +++ b/ExchangeAPI.js @@ -165,6 +165,8 @@ trades.push(trade); } + if (global.LOG_CONTROL[MODULE_NAME].logContent === true) { logger.write(MODULE_NAME, "[INFO] getExecutedTrades -> onExchangeCallReturned -> trades = " + JSON.stringify(trades)); } + callBackFunction(global.DEFAULT_OK_RESPONSE, trades); } } From b6a2b5c2467d354334337fcc6ed055101b175d49 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 27 Jul 2018 11:11:29 +0200 Subject: [PATCH 2/9] Genes Implementation --- Context.js | 14 +-- PoloniexAPIClient.js | 5 +- Root.js | 164 ++++++++++++++++++++++++++++------- Run.js | 2 + StatusReport.js | 20 ++++- TradingBotProcessMainLoop.js | 12 +-- package-lock.json | 10 ++- package.json | 4 +- 8 files changed, 180 insertions(+), 51 deletions(-) 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" + } } From 1b9da5763be3d6a98dbc9cf481b4eb93140b2fdf Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 27 Jul 2018 14:24:02 +0200 Subject: [PATCH 3/9] Bug Fixes Genes Implementation --- Root.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Root.js b/Root.js index 696fa6251..56cac4d89 100644 --- a/Root.js +++ b/Root.js @@ -831,9 +831,12 @@ exports.newRoot = function newRoot() { } - botConfig.filePathRoot = botConfig.filePathRoot + "/" + "Clon" + clonKey; + let clonName = "Clon" + clonKey; + + botConfig.filePathRoot = botConfig.devTeam + "/" + botConfig.codeName + "-" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; + botConfig.instance = "Clon" + clonKey; - setTimeout(execute, i * 2 * 1000); + setTimeout(execute, i * Math.random() * 10 * 1000); function execute() { @@ -846,9 +849,9 @@ exports.newRoot = function newRoot() { /* If the bot does not have any genetic rules at all */ let genes = {}; - botConfig.instance = "Master"; + pBotConfig.instance = "Master"; - createBotInstance(genes, 1, botConfig); + createBotInstance(genes, 1, pBotConfig); } From b6b87282b03b7df47a3ebf35c8500b31a0b6080f Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 28 Jul 2018 15:28:16 +0200 Subject: [PATCH 4/9] Multi-Exchange Keys --- ExchangeAPI.js | 2 +- Root.js | 3 +++ Run.js | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ExchangeAPI.js b/ExchangeAPI.js index 744c7ac65..807061836 100644 --- a/ExchangeAPI.js +++ b/ExchangeAPI.js @@ -29,7 +29,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - poloniexApiClient = POLONIEX_CLIENT_MODULE.newPoloniexAPIClient(global.EXCHANGE_KEYS[global.EXCHANGE_NAME].Key, global.EXCHANGE_KEYS[global.EXCHANGE_NAME].Secret); + poloniexApiClient = POLONIEX_CLIENT_MODULE.newPoloniexAPIClient(global.EXCHANGE_KEYS[global.EXCHANGE_NAME][bot.instanceIndex].Key, global.EXCHANGE_KEYS[global.EXCHANGE_NAME][bot.instanceIndex].Secret); callBackFunction(global.DEFAULT_OK_RESPONSE); diff --git a/Root.js b/Root.js index 56cac4d89..86a911235 100644 --- a/Root.js +++ b/Root.js @@ -836,6 +836,8 @@ exports.newRoot = function newRoot() { botConfig.filePathRoot = botConfig.devTeam + "/" + botConfig.codeName + "-" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion; botConfig.instance = "Clon" + clonKey; + botConfig.instanceIndex = i; + setTimeout(execute, i * Math.random() * 10 * 1000); function execute() { @@ -850,6 +852,7 @@ exports.newRoot = function newRoot() { let genes = {}; pBotConfig.instance = "Master"; + pBotConfig.instanceIndex = 0; createBotInstance(genes, 1, pBotConfig); diff --git a/Run.js b/Run.js index ffe8d766f..a93071179 100644 --- a/Run.js +++ b/Run.js @@ -99,10 +99,10 @@ function readExchangeAPIKey() { console.log("[HINT] You need to have a file at this path -> " + filePath); global.EXCHANGE_KEYS = { - Poloniex: { + Poloniex: [{ Key: "", Secret: "" - } + }] } startRoot(); From 7ff13067a14e1beeacab6dc6b2dc19681287f277 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 28 Jul 2018 17:53:23 +0200 Subject: [PATCH 5/9] Returning the Nonce where it was originally. --- PoloniexAPIClient.js | 5 +++-- Run.js | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/PoloniexAPIClient.js b/PoloniexAPIClient.js index bc6ce916e..fc2dc534a 100644 --- a/PoloniexAPIClient.js +++ b/PoloniexAPIClient.js @@ -18,7 +18,8 @@ // Module dependencies var crypto = require('crypto'), - request = require('request'); + request = require('request'), + nonce = require('nonce')(); // Constants var version = '0.0.8', @@ -121,7 +122,7 @@ parameters || (parameters = {}); parameters.command = command; - parameters.nonce = global.nonce(); + parameters.nonce = nonce(); options = { method: 'POST', diff --git a/Run.js b/Run.js index a93071179..4911e433d 100644 --- a/Run.js +++ b/Run.js @@ -32,8 +32,6 @@ 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() { From 70b066822db086e81cc352089ded5de58bfe2a69 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 29 Jul 2018 00:25:55 +0200 Subject: [PATCH 6/9] No Exchange Response Handled --- PoloniexAPIClient.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/PoloniexAPIClient.js b/PoloniexAPIClient.js index fc2dc534a..0202f49cd 100644 --- a/PoloniexAPIClient.js +++ b/PoloniexAPIClient.js @@ -415,6 +415,14 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeErr = " + stringExchangeErr); } if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] analizeResponse -> exchangeResponse = " + stringExchangeResponse); } + if (stringExchangeResponse === undefined) { + + logger.write(MODULE_NAME, "[WARN] analizeResponse -> No response received from the exchange. Retrying Later."); + + notOkCallBack(global.DEFAULT_RETRY_RESPONSE); + return; + } + if (stringExchangeErr.indexOf("ETIMEDOUT") > 0 || stringExchangeErr.indexOf("ENOTFOUND") > 0 || stringExchangeErr.indexOf("ECONNREFUSED") > 0 || From cf13f2f5e7e0c4c31bf0c3a279b30ebc02a768d5 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 29 Jul 2018 09:48:38 +0200 Subject: [PATCH 7/9] New condition, NONCE collition --- PoloniexAPIClient.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/PoloniexAPIClient.js b/PoloniexAPIClient.js index 0202f49cd..5674773fb 100644 --- a/PoloniexAPIClient.js +++ b/PoloniexAPIClient.js @@ -432,10 +432,11 @@ stringExchangeResponse.indexOf("Connection timed out") > 0 || stringExchangeResponse.indexOf("Connection Error") > 0 || stringExchangeResponse.indexOf("Bad gateway") > 0 || + stringExchangeResponse.indexOf("Nonce must be greater than") > 0 || stringExchangeResponse.indexOf("Internal error. Please try again") > 0))) { - logger.write(MODULE_NAME, "[WARN] analizeResponse -> Timeout reached or connection problem while trying to access the Exchange API. Requesting new execution later."); - logger.write(MODULE_NAME, "[WARN] analizeResponse -> stringExchangeErr = " + stringExchangeErr); + logger.write(MODULE_NAME, "[ERROR] analizeResponse -> Somethng bad happened while trying to access the Exchange API. Requesting new execution later."); + logger.write(MODULE_NAME, "[ERROR] analizeResponse -> stringExchangeErr = " + stringExchangeErr); notOkCallBack(global.DEFAULT_RETRY_RESPONSE); return; From fe469f38c7111c1ff70cb676d5a166edd326610b Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 29 Jul 2018 11:41:01 +0200 Subject: [PATCH 8/9] Initial Investment Doubled so that algobots trade above the minimun of 1 USDT --- Context.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Context.js b/Context.js index 62d3842a7..133598a8b 100644 --- a/Context.js +++ b/Context.js @@ -330,7 +330,7 @@ */ 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. + const INITIAL_INVESTMENT_B = .002 / totalAlgobots; // This is just for this release of the platform. thisObject.executionContext = { investment: { // This is used to calculate profits. From 2c9e62f1b67473d467453f6cf001976289ff9fdf Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 31 Jul 2018 11:15:46 +0200 Subject: [PATCH 9/9] Genetic Rules Refactored to Genes --- Root.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Root.js b/Root.js index 86a911235..2e689d2a0 100644 --- a/Root.js +++ b/Root.js @@ -759,19 +759,19 @@ exports.newRoot = function newRoot() { if (FULL_LOG === true) { console.log(logDisplace + "[INFO] start -> findProcess -> runTradingBot -> Entering function."); } - if (pBotConfig.geneticRules !== undefined) { + if (pBotConfig.genes !== undefined) { - /* Here, based on the genetic rules we will create one instance for each combination of genes */ + /* Here, based on the gene we will create one instance for each combination of genes */ let valueMatrix = []; - for (let i = 0; i < pBotConfig.geneticRules.length; i++) { + for (let i = 0; i < pBotConfig.genes.length; i++) { - let rule = pBotConfig.geneticRules[i]; + let gene = pBotConfig.genes[i]; let possibleValues = []; - for (let j = rule.lowerLimit; j <= rule.upperLimit; j++) { + for (let j = gene.lowerLimit; j <= gene.upperLimit; j++) { possibleValues.push(j); @@ -824,9 +824,9 @@ exports.newRoot = function newRoot() { let genes = {}; let clonKey = ""; - for (let j = 0; j < botConfig.geneticRules.length; j++) { + for (let j = 0; j < botConfig.genes.length; j++) { - genes[botConfig.geneticRules[j].name] = combination[j]; + genes[botConfig.genes[j].name] = combination[j]; clonKey = clonKey + "." + combination[j]; } @@ -848,7 +848,7 @@ exports.newRoot = function newRoot() { } } else { - /* If the bot does not have any genetic rules at all */ + /* If the bot does not have any genes at all */ let genes = {}; pBotConfig.instance = "Master";