From aedc957f204440a29da928f3997c9d1c6c1a985c Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 10 Aug 2019 18:24:48 +0200 Subject: [PATCH 01/13] Reading the exact fields from the designer --- Run.js | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Run.js b/Run.js index 979d075be..aec97a177 100644 --- a/Run.js +++ b/Run.js @@ -68,11 +68,30 @@ function sequenceExecution(currentStep, notFirstSequence) { execution.exchangeName ? global.EXCHANGE_NAME = execution.exchangeName : undefined; - if (definition.personalData) { - process.env.KEY = definition.personalData.exchangeAccounts[0].keys[0].code; - process.env.SECRET = definition.personalData.exchangeAccounts[0].keys[1].code; + if (definition) + { + if (definition.personalData) { + if (definition.personalData.exchangeAccounts) { + if (definition.personalData.exchangeAccounts.length > 0) { + let exchangeAccount = definition.personalData.exchangeAccounts[0] + if (exchangeAccount.keys) { + if (exchangeAccount.keys.length > 0) { + let key = exchangeAccount.keys[0] + try { + let data = JSON.parse(key.code) + process.env.KEY = data.label + process.env.SECRET = data.secret + } catch (err) { + // No need to do anything if data is wrong for now. + } + } + } + } + } + } } + let stepKey = execution.devTeam + '.' + execution.bot + '.' + execution.process; if (processedSteps.has(stepKey)) { processedSteps.set(stepKey, processedSteps.get(stepKey) + 1); From e080ada2b47ee458d5d0886daeb25838b426dda3 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 10 Aug 2019 18:40:15 +0200 Subject: [PATCH 02/13] Key name and secret --- Run.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Run.js b/Run.js index aec97a177..536093fb7 100644 --- a/Run.js +++ b/Run.js @@ -77,13 +77,10 @@ function sequenceExecution(currentStep, notFirstSequence) { if (exchangeAccount.keys) { if (exchangeAccount.keys.length > 0) { let key = exchangeAccount.keys[0] - try { - let data = JSON.parse(key.code) - process.env.KEY = data.label - process.env.SECRET = data.secret - } catch (err) { - // No need to do anything if data is wrong for now. - } + + process.env.KEY = key.name + process.env.SECRET = key.code + } } } From b110e8be682610a34d2541683204f3353ff1cdfb Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sat, 10 Aug 2019 19:45:26 +0200 Subject: [PATCH 03/13] Adjusting First Sequence --- Run.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Run.js b/Run.js index 536093fb7..a6eed7422 100644 --- a/Run.js +++ b/Run.js @@ -34,17 +34,19 @@ let sequenceList = require('./sequence'); let isRunSequence = false; let sequenceStep = 0; let processedSteps = new Map() +notFirstSequence = false + if (process.env.RUN_SEQUENCE !== undefined) { isRunSequence = JSON.parse(process.env.RUN_SEQUENCE) } if (isRunSequence) { - sequenceExecution(sequenceStep, false) + sequenceExecution(sequenceStep) } else { readExecutionConfiguration() } -function sequenceExecution(currentStep, notFirstSequence) { +function sequenceExecution(currentStep) { let execution = sequenceList[currentStep]; process.env.STOP_GRACEFULLY = true; @@ -106,17 +108,18 @@ function onExecutionFinish(result, finishStepKey) { console.log('[INFO] onExecutionFinish -> Step already processed.') } else { if (sequenceStep < sequenceList.length) { - sequenceExecution(sequenceStep, true) + sequenceExecution(sequenceStep) } else { if (sequenceStep < sequenceList.length) { - sequenceExecution(sequenceStep, true); + sequenceExecution(sequenceStep); } else { setTimeout(function () { console.log("[INFO] onExecutionFinish -> New round for sequence execution started."); sequenceList = require('./sequence'); // We read again the sequence after every loop sequenceStep = 0; processedSteps = new Map(); - sequenceExecution(sequenceStep, true); + sequenceExecution(sequenceStep); + notFirstSequence = true }, process.env.EXECUTION_LOOP_DELAY); } } From 1afc012a2f2e0d3a9ddc5667b92782866f705164 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 11 Aug 2019 14:18:09 +0200 Subject: [PATCH 04/13] Multiple Fixes to allow it to run without user keys, in BACKTEST mode. --- Assistant.js | 12 ++++---- MultiPeriodDaily.js | 14 ++++++++-- MultiPeriodMarket.js | 9 ++++-- Root.js | 4 +++ Run.js | 49 +++++++++++++++++++++++++++++++-- TradingEngineProcessMainLoop.js | 2 -- sequence.json | 5 +--- 7 files changed, 78 insertions(+), 17 deletions(-) diff --git a/Assistant.js b/Assistant.js index 1ef164205..810cf8f75 100644 --- a/Assistant.js +++ b/Assistant.js @@ -157,11 +157,13 @@ let candleArray; - if (err.result === global.CUSTOM_FAIL_RESPONSE.result) { // Just past midnight, this file will not exist for a couple of minutes. - if (err.message === "File does not exist." || err.message === "The specified key does not exist.") { - callBackFunction(global.DEFAULT_RETRY_RESPONSE); - return; - } + if (err.result === global.CUSTOM_FAIL_RESPONSE.result || err.code === "The specified key does not exist." || err.message === "File does not exist.") { // Just past midnight, this file will not exist for a couple of minutes. + + logger.write(MODULE_NAME, "[WARN] initialize -> getMarketRateFromIndicator -> onFileReceived -> err = " + JSON.stringify(err)); + logger.write(MODULE_NAME, "[WARN] initialize -> getMarketRateFromIndicator -> This could happen when there are still holes on trades and the process needs to catch up. "); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } if (err.result === global.DEFAULT_OK_RESPONSE.result) { diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 003f97ec8..caa3b6672 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -409,7 +409,12 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> Entering function."); } let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2); - let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + let filePath + if (dependency.dataSet === "Multi-Period-Daily") { + filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel + "/" + dateForPath; + } else { + filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath; + } let fileName = market.assetA + '_' + market.assetB + ".json"; storage.getTextFile(filePath, fileName, onFileReceived); @@ -474,7 +479,12 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> Entering function."); } let dateForPath = bot.multiPeriodDailyProcessDatetime.getUTCFullYear() + '/' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.multiPeriodDailyProcessDatetime.getUTCDate(), 2); - let filePath = dependency.product + '/' + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + let filePath + if (dependency.dataSet === "Multi-Period-Daily") { + filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel + "/" + dateForPath; + } else { + filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath; + } let fileName = market.assetA + '_' + market.assetB + ".json"; storage.getTextFile(filePath, fileName, onFileReceived); diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index ceab3ff19..b78128fcf 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -168,10 +168,15 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> Entering function."); } + let dateForPath = bot.processDatetime.getUTCFullYear() + '/' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '/' + utilities.pad(bot.processDatetime.getUTCDate(), 2); let fileName = market.assetA + '_' + market.assetB + ".json"; - let filePath = dependency.product + "/" + "Multi-Period-Market" + "/" + outputPeriodLabel; - + let filePath + if (dependency.dataSet === "Multi-Period-Market") { + filePath = dependency.product + '/' + dependency.dataSet + "/" + outputPeriodLabel; + } else { + filePath = dependency.product + '/' + dependency.dataSet + "/" + dateForPath; + } storage.getTextFile(filePath, fileName, onFileReceived); function onFileReceived(err, text) { diff --git a/Root.js b/Root.js index fe4275081..d753fd8bc 100644 --- a/Root.js +++ b/Root.js @@ -443,6 +443,10 @@ runTradingBot(botConfig, processConfig); break; } + case 'Trading-Engine': { + runTradingEngine(botConfig, processConfig); + break; + } default: { console.log(logDisplace + "Root : [ERROR] start -> findProcess -> Unexpected bot type. -> botConfig.type = " + botConfig.type); } diff --git a/Run.js b/Run.js index a6eed7422..f4a3fe316 100644 --- a/Run.js +++ b/Run.js @@ -82,7 +82,7 @@ function sequenceExecution(currentStep) { process.env.KEY = key.name process.env.SECRET = key.code - + } } } @@ -90,7 +90,6 @@ function sequenceExecution(currentStep) { } } - let stepKey = execution.devTeam + '.' + execution.bot + '.' + execution.process; if (processedSteps.has(stepKey)) { processedSteps.set(stepKey, processedSteps.get(stepKey) + 1); @@ -142,6 +141,14 @@ async function readExecutionConfiguration(execution) { let finalDatetime = process.env.END_DATE_TIME if (execution.type === 'Trading-Engine') { + + /* We set the START MODE of the Trading Engine */ + if (process.env.KEY === undefined || process.env.SECRET === undefined) { + process.env.START_MODE = "backtest" // if we dont have keys, we swtich to backtest mode to avoid exchange errors. + } else { + process.env.START_MODE = "live" // If we have keys, then we are in live mode. + } + if (definition !== undefined) { if (definition.simulationParams !== undefined) { if (definition.simulationParams.beginDatetime !== undefined) { @@ -178,6 +185,44 @@ async function readExecutionConfiguration(execution) { } } } + /* Get the initial balance from the definition */ + let tradingSystem = definition.tradingSystem + + if (tradingSystem) { + if (tradingSystem.parameters !== undefined) { + if (tradingSystem.parameters.baseAsset !== undefined) { + if (tradingSystem.parameters.baseAsset.formula !== undefined) { + let receivedParameters + try { + receivedParameters = JSON.parse(tradingSystem.parameters.baseAsset.formula.code); + + if (receivedParameters.name !== undefined) { + baseAsset = receivedParameters.name; + if (baseAsset !== 'BTC' && baseAsset !== 'USDT') { + /* using BTC as default */ + baseAsset = 'BTC' + } + } + + if (baseAsset === 'BTC') { + if (receivedParameters.initialBalance !== undefined) { + process.env.INITIAL_BALANCE_ASSET_A = receivedParameters.initialBalance; + process.env.INITIAL_BALANCE_ASSET_B = 0 + } + } else { + if (receivedParameters.initialBalance !== undefined) { + process.env.INITIAL_BALANCE_ASSET_B = receivedParameters.initialBalance; + process.env.INITIAL_BALANCE_ASSET_A = 0 + } + } + } catch (err) { + process.env.INITIAL_BALANCE_ASSET_A = 0.001 // default + process.env.INITIAL_BALANCE_ASSET_B = 0 // default + } + } + } + } + } } } diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index 19db8df72..2da74a9c0 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -36,8 +36,6 @@ try { if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - bot.startMode = 'Live' // The Trading Engine does not support different start modes. Only live for background compatibility. - UI_COMMANDS = pUI_COMMANDS; processConfig = pProcessConfig; diff --git a/sequence.json b/sequence.json index fa8694f9a..10ca0ec47 100644 --- a/sequence.json +++ b/sequence.json @@ -140,9 +140,6 @@ "exchangeName": "Poloniex", "process": "Multi-Period-Daily", "beginDatetime": "2019-08-01T08:00:00.000Z", - "timePeriod": "05-min", - "baseAsset": "assetB", - "balanceAssetA": "0", - "balanceAssetB": "0.001" + "timePeriod": "05-min" } ] From 71f149f2982a5c76745df154ef18740fb093d9a2 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 12 Aug 2019 11:08:10 +0200 Subject: [PATCH 05/13] Logging err.stack --- Assistant.js | 38 ++++----- CloudUtilities.js | 2 +- Context.js | 28 +++---- DataDependencies.js | 4 +- DataSet.js | 6 +- DebugLog.js | 8 +- IndicatorBotProcessMainLoop.js | 30 ++++---- MultiPeriodDaily.js | 48 ++++++------ MultiPeriodMarket.js | 28 +++---- Root.js | 32 ++++---- Run.js | 3 +- SensorBotProcessMainLoop.js | 22 +++--- StatusDependencies.js | 6 +- StatusReport.js | 40 +++++----- TradingBotProcessMainLoop.js | 38 ++++----- TradingEngineProcessMainLoop.js | 38 ++++----- sequence.json | 132 -------------------------------- 17 files changed, 185 insertions(+), 318 deletions(-) diff --git a/Assistant.js b/Assistant.js index 810cf8f75..f1f4f3611 100644 --- a/Assistant.js +++ b/Assistant.js @@ -114,13 +114,13 @@ validateExchangeSyncronicity(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromExchange -> onTicker -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromExchange -> onTicker -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromExchange -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromExchange -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -213,7 +213,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromIndicator -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> getMarketRateFromIndicator -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -255,13 +255,13 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> validateExchangeSyncronicity -> onDone -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> validateExchangeSyncronicity -> onDone -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -315,14 +315,14 @@ callBackFunction(global.DEFAULT_OK_RESPONSE); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> calculateProfits -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> calculateProfits -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); return; } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -401,7 +401,7 @@ } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] getPositionsAtExchange -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] getPositionsAtExchange -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } @@ -628,12 +628,12 @@ break; } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> onResponse -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> onResponse -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> getPositionTradesAtExchange -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } @@ -706,7 +706,7 @@ next(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> confirmOrderWasExecuted -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> confirmOrderWasExecuted -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); return; } @@ -792,7 +792,7 @@ next(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> confirmOrderWasPartiallyExecuted -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); return; } @@ -867,14 +867,14 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> applyTradesToContext -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> applyTradesToContext -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); return; } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> loopBody -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); return; } @@ -913,7 +913,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] ordersExecutionCheck -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } @@ -1077,12 +1077,12 @@ break; } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] putPosition -> onResponse -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] putPosition -> onResponse -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] putPosition -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] putPosition -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -1201,12 +1201,12 @@ break; } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] movePosition -> onResponse -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] movePosition -> onResponse -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] movePosition -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] movePosition -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/CloudUtilities.js b/CloudUtilities.js index a22f9e2a3..1c8a9ccb6 100644 --- a/CloudUtilities.js +++ b/CloudUtilities.js @@ -46,7 +46,7 @@ exports.newCloudUtilities = function newCloudUtilities(logger) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] createFolderIfNeeded -> loop -> checkLoop -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] createFolderIfNeeded -> loop -> checkLoop -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] createFolderIfNeeded -> loop -> checkLoop -> err = "+ err.stack); callBackFunction(err); return; } diff --git a/Context.js b/Context.js index 47e9a960b..62a6af57f 100644 --- a/Context.js +++ b/Context.js @@ -120,7 +120,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> onDone -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -151,7 +151,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> getStatusReport -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> getStatusReport -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } @@ -205,7 +205,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionHistory -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionHistory -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } @@ -231,7 +231,7 @@ function onFileReceived(err, text) { if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> onFileReceived -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> onFileReceived -> err = "+ err.stack); callBack(err); return; } @@ -272,7 +272,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> getExecutionContext -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } @@ -338,13 +338,13 @@ callBack(global.DEFAULT_OK_RESPONSE); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> createConext -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> createConext -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -385,7 +385,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] saveThemAll -> onDone -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] saveThemAll -> onDone -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -415,7 +415,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExecutionContext -> onFileCreated -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExecutionContext -> onFileCreated -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExecutionContext -> onFileCreated -> err = "+ err.stack); callBack(err); return; } @@ -426,7 +426,7 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExecutionContext -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExecutionContext -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -476,7 +476,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExucutionHistory -> onFileCreated -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> onFileCreated -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> onFileCreated -> err = "+ err.stack); callBack(err); return; } @@ -498,7 +498,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] saveThemAll -> writeExucutionHistory -> onFileCreated -> onSequenceFileCreated -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> onFileCreated -> onSequenceFileCreated -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> onFileCreated -> onSequenceFileCreated -> err = "+ err.stack); callBack(err); return; } @@ -510,7 +510,7 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeExucutionHistory -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -526,7 +526,7 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeStatusReport -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] saveThemAll -> writeStatusReport -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/DataDependencies.js b/DataDependencies.js index f4f508103..61456835a 100644 --- a/DataDependencies.js +++ b/DataDependencies.js @@ -47,7 +47,7 @@ function onInitilized(err) { if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> err = "+ err.stack); alreadyCalledBack = true; callBackFunction(err); @@ -82,7 +82,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/DataSet.js b/DataSet.js index f1f370a1c..ee96308f1 100644 --- a/DataSet.js +++ b/DataSet.js @@ -33,7 +33,7 @@ exports.newDataSet = function newDataSet(BOT, logger) { callBackFunction(global.DEFAULT_OK_RESPONSE); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -59,7 +59,7 @@ exports.newDataSet = function newDataSet(BOT, logger) { } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] 'getTextFile' -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] 'getTextFile' -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -100,7 +100,7 @@ exports.newDataSet = function newDataSet(BOT, logger) { } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] 'createTextFile' -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] 'createTextFile' -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/DebugLog.js b/DebugLog.js index 39eaae594..561178364 100644 --- a/DebugLog.js +++ b/DebugLog.js @@ -35,7 +35,7 @@ exports.newDebugLog = function newDebugLog() { disableLogging = pdisableLogging } catch (err) { - console.log("[ERROR] Debug Log -> initialize -> err = "+ err); + console.log("[ERROR] Debug Log -> initialize -> err = "+ err.stack); } } @@ -94,7 +94,7 @@ exports.newDebugLog = function newDebugLog() { function onFileCreated(err) { if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - console.log("[ERROR] DebugLog -> persist -> onInizialized -> onFileCreated -> err = "+ err); + console.log("[ERROR] DebugLog -> persist -> onInizialized -> onFileCreated -> err = "+ err.stack); setTimeout(writeLog, 10000); // Lets retry until we make it. return; @@ -105,7 +105,7 @@ exports.newDebugLog = function newDebugLog() { } } } catch (err) { - console.log("[ERROR] DebugLog -> persist -> err = "+ err); + console.log("[ERROR] DebugLog -> persist -> err = "+ err.stack); console.log("[ERROR] DebugLog -> persist -> onInizialized -> contentToPersist = " + contentToPersist); } } @@ -134,7 +134,7 @@ exports.newDebugLog = function newDebugLog() { accumulatedLog = accumulatedLog + logLine; } catch (err) { - console.log("[ERROR] DebugLog -> write -> err = "+ err); + console.log("[ERROR] DebugLog -> write -> err = "+ err.stack); } } diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 93911b2db..9e856c6c1 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -75,7 +75,7 @@ } } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -202,7 +202,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -213,7 +213,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -305,7 +305,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -316,7 +316,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -406,7 +406,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -417,7 +417,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -536,7 +536,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -547,7 +547,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -635,7 +635,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -646,7 +646,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -765,7 +765,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -776,7 +776,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -908,7 +908,7 @@ } } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = "+ err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); @@ -917,7 +917,7 @@ } } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index caa3b6672..77eba7115 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -62,7 +62,7 @@ usertBot.initialize(dataDependencies, callBackFunction, pAssistant); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -266,7 +266,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> err = "+ err.stack); if (err.message === "Cannot read property 'file' of undefined") { logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Check the bot configuration to see if all of its statusDependencies declarations are correct. "); logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)); @@ -321,7 +321,7 @@ periodsLoop(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> advanceTime -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> advanceTime -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -344,7 +344,7 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -443,14 +443,14 @@ if ((err.result === "Fail Because" && err.message === "File does not exist.") || err.code === 'The specified key does not exist.') { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = "+ err.stack); callBackFunction(global.DEFAULT_RETRY_RESPONSE); return; } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = "+ err.stack); callBackFunction(err); return; } @@ -461,13 +461,13 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> onFileReceived -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getPreviousFile -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -519,19 +519,19 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> dependencyLoopBody -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> dependencyLoopBody -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -555,7 +555,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> dependencyControlLoop -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> dependencyControlLoop -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -595,19 +595,19 @@ periodsControlLoop(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -637,7 +637,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> controlLoop -> onWritten -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = "+ err.stack); callBackFunction(err); return; } @@ -645,21 +645,21 @@ writeStatusReport(bot.multiPeriodDailyProcessDatetime, advanceTime); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> controlLoop -> onWritten -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsControlLoop -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsControlLoop -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -692,7 +692,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> writeDataRanges -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> writeDataRanges -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } @@ -721,7 +721,7 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> onFileCreated -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> onFileCreated -> err = "+ err.stack); callBack(err); return; } @@ -734,7 +734,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> writeDataRange -> err = "+ err.stack); callBack(global.DEFAULT_FAIL_RESPONSE); } } @@ -757,14 +757,14 @@ bot.hasTheBotJustStarted = false; } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> err = " + err); + logger.write(MODULE_NAME, "[ERROR] start -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index b78128fcf..7d0fec757 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -58,7 +58,7 @@ usertBot.initialize(dataDependencies, callBackFunction, pAssistant); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -124,7 +124,7 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -188,7 +188,7 @@ if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = "+ err.stack); callBackFunction(err); return; } @@ -200,20 +200,20 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> onFileReceived -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getFile -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> dependencyLoopBody -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoop -> dependencyLoopBody -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -237,7 +237,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> dependencyControlLoop -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> dependencyControlLoop -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -274,19 +274,19 @@ periodsControlLoop(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> onBotFinished -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch(err){ - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> callTheBot -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -310,14 +310,14 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsControlLoop -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsControlLoop -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -336,14 +336,14 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/Root.js b/Root.js index d753fd8bc..d53592834 100644 --- a/Root.js +++ b/Root.js @@ -540,7 +540,7 @@ } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> err = "+ err.stack); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bye."); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); @@ -553,16 +553,16 @@ } } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = "+ err.stack); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> Bot will not be started. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = "+ err); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> onInitializeReady -> err = "+ err.stack); logger.persist(); } } } catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> err = "+ err); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runSensorBot -> err = "+ err.stack); } } @@ -611,7 +611,7 @@ } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> err = "+ err.stack); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bye."); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); @@ -622,15 +622,15 @@ } } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = "+ err.stack); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> Failed to initialize the bot. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = "+ err); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> onInitializeReady -> err = "+ err.stack); logger.persist(); } } } catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> err = "+ err); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runIndicatorBot -> err = "+ err.stack); } } @@ -789,7 +789,7 @@ } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> err = "+ err.stack); 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); @@ -800,9 +800,9 @@ } } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = "+ err.stack); 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); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> err = "+ err.stack); logger.persist(); } @@ -810,7 +810,7 @@ } } catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> err = "+ err); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> err = "+ err.stack); } } @@ -854,7 +854,7 @@ } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> err = "+ err.stack); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. "); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bye."); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId); @@ -865,15 +865,15 @@ } } else { - logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> err = "+ err.stack); logger.write(MODULE_NAME, "[ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> Failed to initialize the bot. "); - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> err = ", err); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingEngine -> onInitializeReady -> err = "+ err.stack); logger.persist(); } } } catch (err) { - console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingEngine -> err = ", err); + console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingEngine -> err = "+ err.stack); } } diff --git a/Run.js b/Run.js index f4a3fe316..3ba0a991d 100644 --- a/Run.js +++ b/Run.js @@ -320,9 +320,8 @@ async function readExecutionConfiguration(execution) { } catch (err) { - console.log("[ERROR] readExecutionConfiguration -> err = " + err); + console.log("[ERROR] readExecutionConfiguration -> err = "+ err.stack); console.log("[ERROR] readExecutionConfiguration -> Please verify that the Start Mode for the type of Bot configured applies to that type."); - console.log("[ERROR] readExecutionConfiguration -> err = " + err.stack); } } diff --git a/SensorBotProcessMainLoop.js b/SensorBotProcessMainLoop.js index 3730c6cc9..6bd875c66 100644 --- a/SensorBotProcessMainLoop.js +++ b/SensorBotProcessMainLoop.js @@ -73,7 +73,7 @@ } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -197,7 +197,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -208,7 +208,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -271,7 +271,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -282,7 +282,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -380,7 +380,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -391,7 +391,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -510,7 +510,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -521,7 +521,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -679,7 +679,7 @@ } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = "+ err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); @@ -690,7 +690,7 @@ } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); diff --git a/StatusDependencies.js b/StatusDependencies.js index 13a100455..75b273431 100644 --- a/StatusDependencies.js +++ b/StatusDependencies.js @@ -39,7 +39,7 @@ function onInitilized(err) { if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> err = "+ err.stack); alreadyCalledBack = true; callBackFunction(err); @@ -94,7 +94,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> onLoad -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -128,7 +128,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/StatusReport.js b/StatusReport.js index 8be203686..6023575eb 100644 --- a/StatusReport.js +++ b/StatusReport.js @@ -56,7 +56,7 @@ } callBackFunction(global.DEFAULT_OK_RESPONSE); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -98,7 +98,7 @@ if ( err.result === global.CUSTOM_FAIL_RESPONSE.result && (err.message === 'Folder does not exist.' || err.message === 'File does not exist.') || err.code === "The specified key does not exist.") { - logger.write(MODULE_NAME, "[INFO] load -> onFileReceived -> err = "+ err); + logger.write(MODULE_NAME, "[INFO] load -> onFileReceived -> err = "+ err.stack); /* In this case we can assume that this is the first execution ever of this bot.*/ @@ -114,7 +114,7 @@ } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] load -> onFileReceived -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] load -> onFileReceived -> err = "+ err.stack); callBackFunction(err); return; } @@ -148,7 +148,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] load -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] load -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -190,7 +190,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] save -> onFileCreated -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] save -> onFileCreated -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] save -> onFileCreated -> err = "+ err.stack); callBackFunction(err); return; } @@ -205,7 +205,7 @@ } catch (err) { - logger.write(MODULE_NAME, "[ERROR] save -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] save -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -246,7 +246,7 @@ err.result === global.CUSTOM_FAIL_RESPONSE.result && (err.message === 'Status Report was never created.') ) { - logger.write(MODULE_NAME, "[INFO] verifyMarketComplete -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[INFO] verifyMarketComplete -> onLoad -> err = "+ err.stack); /* The first month of the market didnt create the main report yet. Aborting verification. */ @@ -257,7 +257,7 @@ } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> onLoad -> err = "+ err.stack); callBackFunction(err); return; } @@ -270,7 +270,7 @@ loopCycle(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> onLoad -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } @@ -300,7 +300,7 @@ err.result === global.CUSTOM_FAIL_RESPONSE.result && (err.message === 'Status Report was never created.') ) { - logger.write(MODULE_NAME, "[INFO] verifyMarketComplete -> loopCycle -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[INFO] verifyMarketComplete -> loopCycle -> onLoad -> err = "+ err.stack); /* The first month of the market didnt create the main report yet. Aborting verification. */ @@ -311,7 +311,7 @@ } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> onLoad -> err = "+ err.stack); callBackFunction(err); return; } @@ -331,13 +331,13 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> onLoad -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } @@ -364,7 +364,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> err = "+ err.stack); callBackFunction(err); return; } @@ -384,7 +384,7 @@ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> onSave -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> onSave -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> onSave -> err = "+ err.stack); callBackFunction(err); return; } @@ -392,7 +392,7 @@ loop(); // Lets see the next month. } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> onSave -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> onSave -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } @@ -407,13 +407,13 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> readAndWriteNewReport -> onLoad -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loopCycle -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } @@ -447,14 +447,14 @@ loopCycle(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loop -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> loop -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] verifyMarketComplete -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return; } diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index dc00aa04f..f477d4a2b 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -72,7 +72,7 @@ } } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -334,7 +334,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -345,7 +345,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -408,7 +408,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -419,7 +419,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -481,7 +481,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -492,7 +492,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -555,7 +555,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -566,7 +566,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -628,7 +628,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -639,7 +639,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -702,7 +702,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -713,7 +713,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -774,7 +774,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -785,7 +785,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -851,7 +851,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -862,7 +862,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -882,7 +882,7 @@ loopControl(nextWaitTime); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> updateClonesModule -> err = "+ err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> updateClonesModule -> err = "+ err.stack); logger.write(MODULE_NAME, "[ERROR] run -> loop -> updateClonesModule -> Execution will continue anyways. "); nextWaitTime = 'Normal'; loopControl(nextWaitTime); @@ -1030,7 +1030,7 @@ } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err); + parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index 2da74a9c0..d43569348 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -77,7 +77,7 @@ } } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = ", err); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -207,7 +207,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -218,7 +218,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -281,7 +281,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -292,7 +292,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -354,7 +354,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -365,7 +365,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -428,7 +428,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeContext -> onInizialized -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -439,7 +439,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeExchangeAPI -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -530,7 +530,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -541,7 +541,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeAssistant -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -629,7 +629,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -640,7 +640,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -759,7 +759,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -770,7 +770,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -836,7 +836,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> onFinished -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -847,7 +847,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> err = ", err); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> saveContext -> err = "+ err.stack); logger.persist(); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); @@ -980,7 +980,7 @@ } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = ", err); + parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = "+ err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); @@ -989,7 +989,7 @@ } } } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> err = ", err); + parentLogger.write(MODULE_NAME, "[ERROR] run -> err = "+ err.stack); clearInterval(fixedTimeLoopIntervalHandle); clearTimeout(nextLoopTimeoutHandle); clearTimeout(checkLoopHealthHandle); diff --git a/sequence.json b/sequence.json index 10ca0ec47..98d47e959 100644 --- a/sequence.json +++ b/sequence.json @@ -1,136 +1,4 @@ [ - { - "devTeam": "AAMasters", - "bot": "AACharly", - "mode": "noTime", - "resumeExecution": true, - "type": "Sensor", - "exchangeName": "Poloniex", - "process": "Live-Trades", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AACharly", - "mode": "noTime", - "resumeExecution": true, - "type": "Sensor", - "exchangeName": "Poloniex", - "process": "Hole-Fixing", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AABruce", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Single-Period-Daily", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AAOlivia", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Daily", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AAOlivia", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Market", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AATom", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Daily", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AATom", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Market", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AAChris", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Daily", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AAChris", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Market", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AAPaula", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Daily", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, - { - "devTeam": "AAMasters", - "bot": "AAPaula", - "mode": "noTime", - "resumeExecution": true, - "type": "Indicator", - "exchangeName": "Poloniex", - "process": "Multi-Period-Market", - "startYear": 2019, - "endYear": 2021, - "month": 1 - }, { "devTeam": "AAMasters", "bot": "AAJason", From cc8b3c49098fa72d77e06b6650f0f682c302adb2 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 12 Aug 2019 12:25:10 +0200 Subject: [PATCH 06/13] BUG FIX --- MultiPeriodMarket.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 7d0fec757..38747554f 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -9,6 +9,8 @@ start: start }; + let utilities = UTILITIES.newCloudUtilities(logger); + let statusDependencies; let dataDependencies; let storages = []; From befa134eb6b8466bf6bb6b76b491befa401c5d10 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 12 Aug 2019 13:02:47 +0200 Subject: [PATCH 07/13] Condtional Logging --- DebugLog.js | 4 +- sequence.json | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/DebugLog.js b/DebugLog.js index 561178364..a80582a86 100644 --- a/DebugLog.js +++ b/DebugLog.js @@ -129,7 +129,9 @@ exports.newDebugLog = function newDebugLog() { let message = "['" + newDate + "'," + messageId + ",'" + pModule + "','" + pMessage + "']" let logLine = '\r\n' + message; - console.log(message) + if (process.env.INTER_PROCESS_FILES_PATH === "true" || message.indexOf("ERROR") > 0) { + console.log(message) + } accumulatedLog = accumulatedLog + logLine; diff --git a/sequence.json b/sequence.json index 98d47e959..10ca0ec47 100644 --- a/sequence.json +++ b/sequence.json @@ -1,4 +1,136 @@ [ + { + "devTeam": "AAMasters", + "bot": "AACharly", + "mode": "noTime", + "resumeExecution": true, + "type": "Sensor", + "exchangeName": "Poloniex", + "process": "Live-Trades", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AACharly", + "mode": "noTime", + "resumeExecution": true, + "type": "Sensor", + "exchangeName": "Poloniex", + "process": "Hole-Fixing", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AABruce", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Single-Period-Daily", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AAOlivia", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Daily", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AAOlivia", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Market", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AATom", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Daily", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AATom", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Market", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AAChris", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Daily", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AAChris", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Market", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AAPaula", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Daily", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, + { + "devTeam": "AAMasters", + "bot": "AAPaula", + "mode": "noTime", + "resumeExecution": true, + "type": "Indicator", + "exchangeName": "Poloniex", + "process": "Multi-Period-Market", + "startYear": 2019, + "endYear": 2021, + "month": 1 + }, { "devTeam": "AAMasters", "bot": "AAJason", From cc9ba1d9fc79a55ddfb83433d1686a9d442ae989 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 12 Aug 2019 13:11:19 +0200 Subject: [PATCH 08/13] Better Logging --- Integrations/FileStorage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Integrations/FileStorage.js b/Integrations/FileStorage.js index 5f9c7ce03..539cc3a92 100644 --- a/Integrations/FileStorage.js +++ b/Integrations/FileStorage.js @@ -105,13 +105,13 @@ exports.newFileStorage = function newFileStorage() { } async function createTextFile(container, filePath, fileContent, callBackFunction) { - logInfo('createTextFile -> Entering function: ' + container.toLowerCase() + '/...' + filePath.substring(filePath.length - 110, filePath.length)) try { let host = await getDevTeamHost(container) if (host.url.indexOf('localhost') !== -1) { - let fileLocation = process.env.STORAGE_PATH + '/' + container + '/' + filePath + let fileLocation = process.env.STORAGE_PATH + '/' + container + '/' + filePath + logInfo('createTextFile: ' + fileLocation) let directoryPath = fileLocation.substring(0, fileLocation.lastIndexOf('/') + 1); mkDirByPathSync(directoryPath) await writeFileAsync(fileLocation, fileContent) From 51d73ff278f12e1e4b99661fc42637dc9eb79aed Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 12 Aug 2019 14:04:37 +0200 Subject: [PATCH 09/13] Bots from its own place --- Integrations/FileStorage.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Integrations/FileStorage.js b/Integrations/FileStorage.js index 539cc3a92..68014bd70 100644 --- a/Integrations/FileStorage.js +++ b/Integrations/FileStorage.js @@ -51,8 +51,15 @@ exports.newFileStorage = function newFileStorage() { let host = await getDevTeamHost(container) if (host.url.indexOf('localhost') !== -1) { - let fileLocation = process.env.STORAGE_PATH + '/' + container + '/' + filePath + let fileLocation + + if (filePath.indexOf("/bots/") > 0) { + fileLocation = process.env.BOTS_PATH + '/' + container + '/' + filePath + } else { + fileLocation = process.env.STORAGE_PATH + '/' + container + '/' + filePath + } + logInfo('getTextFile: ' + fileLocation) let fileContent = await readFileAsync(fileLocation) From f78c861c4a00595d71ef91b8ad5e9b1fda535db5 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 13 Aug 2019 11:46:10 +0200 Subject: [PATCH 10/13] BUG Fixes for live trading to work --- Commons.js | 2367 +++++++++++++++++++++++++++++++ Root.js | 2 +- Run.js | 16 +- TradingEngineProcessMainLoop.js | 8 +- User.Bot.js | 556 ++++++++ 5 files changed, 2936 insertions(+), 13 deletions(-) create mode 100644 Commons.js create mode 100644 User.Bot.js diff --git a/Commons.js b/Commons.js new file mode 100644 index 000000000..9ada6529f --- /dev/null +++ b/Commons.js @@ -0,0 +1,2367 @@ +const strategy = require('./Integrations/Strategy') + +exports.newCommons = function newCommons(bot, logger, UTILITIES) { + + const { orderMessage } = require("@superalgos/mqservice") + + const { + MESSAGE_ENTITY, MESSAGE_TYPE, ORDER_CREATOR, ORDER_TYPE, + ORDER_OWNER, ORDER_DIRECTION, ORDER_STATUS, ORDER_EXIT_OUTCOME, + createMessage, getMessage, getExpandedMessage + } = orderMessage.newOrderMessage() + + const FULL_LOG = true; + const LOG_FILE_CONTENT = false; + + const MODULE_NAME = "Commons"; + const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000; + const GMT_SECONDS = ':00.000 GMT+0000'; + + let thisObject = { + initializeData: initializeData, + runSimulation: runSimulation, + buildLRC: buildLRC, + buildPercentageBandwidthMap: buildPercentageBandwidthMap, + buildBollingerBandsMap: buildBollingerBandsMap, + buildBollingerChannelsArray: buildBollingerChannelsArray, + buildBollingerSubChannelsArray: buildBollingerSubChannelsArray, + buildCandles: buildCandles + }; + + let utilities = UTILITIES.newCloudUtilities(bot, logger); + + let LRCMap = new Map(); + let percentageBandwidthMap = new Map(); + let bollingerBandsMap = new Map(); + let bollingerChannelsArray = []; + let bollingerSubChannelsArray = []; + + let candles = []; + + return thisObject; + + function initializeData() { + + LRCMap = new Map(); + percentageBandwidthMap = new Map(); + bollingerBandsMap = new Map(); + bollingerChannelsArray = []; + bollingerSubChannelsArray = []; + + candles = []; + } + + async function runSimulation( + timePeriod, + currentDay, + startDate, + endDate, + interExecutionMemory, + assistant, + callback, + callBackFunction) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Entering function."); } + + let executionArray = []; + let recordsArray = []; + let conditionsArray = []; + let strategiesArray = []; + let tradesArray = []; + let lastObjectsArray = []; + + let definition = await strategy.getStrategy(); + let tradingSystem = definition.tradingSystem; + + /* Initial Default Values */ + + let initialDate = startDate; + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> initialDate = " + initialDate); } + + const DEFAULT_BASE_ASSET_BALANCE = 1 + const DEFAULT_BASE_ASSET_MINIMUN_BALANCE = 0.5 + const DEFAULT_BASE_ASSET_MAXIMUN_BALANCE = 2 + + let initialBalanceA = DEFAULT_BASE_ASSET_BALANCE + let minimumBalanceA = DEFAULT_BASE_ASSET_MINIMUN_BALANCE + let maximumBalanceA = DEFAULT_BASE_ASSET_MAXIMUN_BALANCE + let initialBalanceB = 0 + let minimumBalanceB = 0 + let maximumBalanceB = 0 + let baseAsset = 'BTC' + + /* Parameters Processing */ + + if (tradingSystem.parameters !== undefined) { + if (tradingSystem.parameters.baseAsset !== undefined) { + if (tradingSystem.parameters.baseAsset.formula !== undefined) { + let receivedParameters + try { + receivedParameters = JSON.parse(tradingSystem.parameters.baseAsset.formula.code); + + if (receivedParameters.name !== undefined) { + baseAsset = receivedParameters.name; + if (baseAsset !== 'BTC' && baseAsset !== 'USDT') { + tradingSystem.parameters.baseAsset.formula.error = baseAsset + ' is not supported. Using default: BTC.' + baseAsset = 'BTC' + } + } + + if (baseAsset === 'BTC') { + if (receivedParameters.initialBalance !== undefined) { + initialBalanceA = receivedParameters.initialBalance; + initialBalanceB = 0 + } else { + initialBalanceA = DEFAULT_BASE_ASSET_BALANCE; + initialBalanceB = 0 + } + if (receivedParameters.minimumBalance !== undefined) { + minimumBalanceA = receivedParameters.minimumBalance; + minimumBalanceB = 0 + } else { + minimumBalanceA = DEFAULT_BASE_ASSET_MINIMUN_BALANCE; + minimumBalanceB = 0 + } + if (receivedParameters.maximumBalance !== undefined) { + maximumBalanceA = receivedParameters.maximumBalance; + maximumBalanceB = 0 + } else { + maximumBalanceA = DEFAULT_BASE_ASSET_MAXIMUN_BALANCE; + maximumBalanceB = 0 + } + } else { + if (receivedParameters.initialBalance !== undefined) { + initialBalanceB = receivedParameters.initialBalance; + initialBalanceA = 0 + } else { + initialBalanceB = DEFAULT_BASE_ASSET_BALANCE; + initialBalanceA = 0 + } + if (receivedParameters.minimumBalance !== undefined) { + minimumBalanceB = receivedParameters.minimumBalance; + minimumBalanceA = 0 + } else { + minimumBalanceB = DEFAULT_BASE_ASSET_MINIMUN_BALANCE; + minimumBalanceA = 0 + } + if (receivedParameters.maximumBalance !== undefined) { + maximumBalanceB = receivedParameters.maximumBalance; + maximumBalanceA = 0 + } else { + maximumBalanceB = DEFAULT_BASE_ASSET_MAXIMUN_BALANCE; + maximumBalanceA = 0 + } + } + } catch (err) { + tradingSystem.parameters.baseAsset.formula.error = err.message + } + } + } + } + + /* Strategy and Phases */ + + let currentStrategyIndex = -1; + let strategyStage = 'No Stage'; + + /* Stop Loss Management */ + + const MIN_STOP_LOSS_VALUE = 1 // We can not let the stop be zero to avoid division by 0 error or infinity numbers as a result. + const MAX_STOP_LOSS_VALUE = Number.MAX_SAFE_INTEGER + let stopLoss = 0; + let stopLossPhase = 0; + let stopLossStage = 'No Stage'; + + /* Take Profit Management */ + + const MIN_TAKE_PROFIT_VALUE = 1 // We can not let the buy order be zero to avoid division by 0 error or infinity numbers as a result. + const MAX_TAKE_PROFIT_VALUE = Number.MAX_SAFE_INTEGER + let previousTakeProfit = 0; + let takeProfit = 0; + let takeProfitPhase = 0; + let takeProfitStage = 'No Stage'; + + /* Simulation Records */ + + let tradePositionRate = 0; + let tradePositionSize = 0; + let positionInstant; + + let previousBalanceAssetA = 0; + let previousBalanceAssetB = 0; + let hitRatio = 0; + let ROI = 0; + let days = 0; + let anualizedRateOfReturn = 0; + let type = '""'; + let marketRate = 0; + let takePositionNow = false + + /* Assistant Info */ + + let ticker = assistant.getTicker(); + + /* In some cases we need to know if we are positioned at the last candle of the calendar day, for that we need thse variables. */ + + let lastInstantOfTheDay = currentDay.valueOf() + ONE_DAY_IN_MILISECONDS - 1; + let lastCandle = candles[candles.length - 1]; + + /* These 2 objects will allow us to create separate files for each one of them. */ + + let currentStrategy = { + begin: 0, + end: 0, + status: 0, + number: 0 + } + + let currentTrade = { + begin: 0, + end: 0, + status: 0, + profit: 0, + exitType: 0, + beginRate: 0, + endRate: 0 + } + + /* + The following counters need to survive multiple executions of the similator and keep themselves reliable. + This is challenging when the simulation is executed using Daily Files, since each execution means a new + day and these counters are meant to be kept along the whole market. + + To overcome this problem, we use the interExecutionMemory to record the values of the current execution + when finish. But there are a few details: + + 1. When the process is at the head of the market, it executes multple times at the same day. + 2. The same code serves execution from Market Files. + 3. In Daily Files we are receiving candles from the current day and previous day, so we need to take care of + not adding to the counters duplicate info when processing the day before candles. + + To overcome these challenges we record the values of the counters and variables on the interExecutionMemory only when + the day is complete and if we have a currentDay. That menas that for Market Files we will never use + interExecutionMemory. + */ + + let balanceAssetA = initialBalanceA; + let balanceAssetB = initialBalanceB; + + let lastTradeProfitLoss = 0; + let profit = 0; + let lastTradeROI = 0; + + let roundtrips = 0; + let fails = 0; + let hits = 0; + let periods = 0; + + /* Message to the Simulation Executor */ + + let orderId = 0; + let messageId = 0; + + let yesterday = {}; + + yesterday.balanceAssetA = balanceAssetA; + yesterday.balanceAssetB = balanceAssetB; + + yesterday.lastTradeProfitLoss = 0; + yesterday.profit = 0; + yesterday.lastTradeROI = 0; + + yesterday.Roundtrips = 0; + yesterday.fails = 0; + yesterday.hits = 0; + yesterday.Periods = 0; + + yesterday.orderId = 0; + yesterday.messageId = 0; + + yesterday.hitRatio = 0; + yesterday.ROI = 0; + yesterday.anualizedRateOfReturn = 0; + + if (interExecutionMemory.roundtrips === undefined) { + + /* Initialize the data structure we will use inter execution. */ + + interExecutionMemory.balanceAssetA = balanceAssetA; + interExecutionMemory.balanceAssetB = balanceAssetB; + + interExecutionMemory.lastTradeProfitLoss = lastTradeProfitLoss; + interExecutionMemory.profit = profit; + interExecutionMemory.lastTradeROI = lastTradeROI; + + interExecutionMemory.roundtrips = 0; + interExecutionMemory.fails = 0; + interExecutionMemory.hits = 0; + interExecutionMemory.periods = 0; + + interExecutionMemory.orderId = 0; + interExecutionMemory.messageId = 0; + + interExecutionMemory.hitRatio = 0; + interExecutionMemory.ROI = 0; + interExecutionMemory.anualizedRateOfReturn = 0; + + } else { + + /* We get the initial values from the day previous to the candles we receive at the current execution */ + + if (currentDay.valueOf() >= startDate.valueOf() + ONE_DAY_IN_MILISECONDS) { // Only after the first day we start grabbing the balance from this memory. + + balanceAssetA = interExecutionMemory.balanceAssetA; + balanceAssetB = interExecutionMemory.balanceAssetB; + + yesterday.balanceAssetA = balanceAssetA; + yesterday.balanceAssetB = balanceAssetB; + + } + + lastTradeProfitLoss = interExecutionMemory.lastTradeProfitLoss; + profit = interExecutionMemory.profit; + lastTradeROI = interExecutionMemory.lastTradeROI; + + roundtrips = interExecutionMemory.roundtrips; + fails = interExecutionMemory.fails; + hits = interExecutionMemory.hits; + periods = interExecutionMemory.periods; + + orderId = interExecutionMemory.orderId; + messageId = interExecutionMemory.messageId; + + hitRatio = interExecutionMemory.hitRatio; + ROI = interExecutionMemory.ROI; + anualizedRateOfReturn = interExecutionMemory.anualizedRateOfReturn; + + yesterday.hitRatio = hitRatio; + yesterday.ROI = ROI; + yesterday.anualizedRateOfReturn = anualizedRateOfReturn; + + } + + /* Main Simulation Loop: We go thourgh all the candles at this time period. */ + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Main Simulation Loop -> candles.length = " + candles.length); } + + let i + initializeLoop() + + function initializeLoop() { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> initializeLoop -> Entering function."); } + i = 0 + loop() + } + + function loop() { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> i = " + i); } + + let candle = candles[i]; + let percentageBandwidth = percentageBandwidthMap.get(candle.begin); + let bollingerBand = bollingerBandsMap.get(candle.begin); + let bollingerChannel = getElement(bollingerChannelsArray, candle.begin, candle.end); + let bollingerSubChannel = getElement(bollingerSubChannelsArray, candle.begin, candle.end); + + //let LRC = LRCMap.get(candle.begin); + + /* If any of the needed indicators is missing, then that period is not calculated */ + + if (candle.begin < initialDate.valueOf()) { + controlLoop(); + return + } + if (bollingerBand === undefined) { + controlLoop(); + return + } + if (percentageBandwidth === undefined) { + controlLoop(); + return + } // percentageBandwidth might start after the first few candles. + if (bollingerChannel === undefined) { + controlLoop(); + return + } + if (bollingerSubChannel === undefined) { + controlLoop(); + return + } + + //if (LRC === undefined) { controlLoop(); return} + + periods++; + days = periods * timePeriod / ONE_DAY_IN_MILISECONDS; + + if (currentDay !== undefined) { // This means that we are processing Daily Files + if (candle.end < currentDay.valueOf()) { + yesterday.Periods++; + } + + /* We skip the candle at the head of the market because i has not closed yet. */ + let candlesPerDay = ONE_DAY_IN_MILISECONDS / timePeriod + if (i === candles.length - 1) { + if ((candles.length < candlesPerDay) || (candles.length > candlesPerDay && candles.length < candlesPerDay * 2)) { + /*We are at the head of the market, thus we skip the last candle because it has not close yet. */ + controlLoop(); + return + /* Note here that in the last candle of the first day or the second day it will use an incomplete candle and partially calculated indicators. + if we skip these two periods, then there will be a hole in the file since the last period will be missing. */ + } + } + } else { // We are processing Market Files + if (i === candles.length - 1) { + controlLoop(); + return + } + } + + let lastObjects = { + candle: clone(candle), + //LRC: clone(LRC), + bollingerBand: clone(bollingerBand), + percentageBandwidth: clone(percentageBandwidth), + bollingerChannel: clone(bollingerChannel), + bollingerSubChannel: clone(bollingerSubChannel) + } + + function clone(obj) { + if (null == obj || "object" != typeof obj) return obj; + var copy = obj.constructor(); + for (var attr in obj) { + if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr]; + } + return copy; + } + + lastObjects.candle.previous = undefined; + //lastObjects.LRC.previous = undefined; + lastObjects.bollingerBand.previous = undefined; + lastObjects.percentageBandwidth.previous = undefined; + lastObjects.bollingerChannel.previous = undefined; + lastObjects.bollingerSubChannel.previous = undefined; + + lastObjectsArray.push(lastObjects); + + if (lastObjectsArray.length > 5) { + lastObjectsArray.splice(0, 1); + } + + let conditions = new Map; // Here we store the conditions values that will be use in the simulator for decision making. + let formulas = new Map; + let conditionsArrayRecord = []; // These are the records that will be saved in a file for the plotter to consume. + let conditionsArrayValues = []; // Here we store the conditions values that will be written on file for the plotter. + let formulasErrors = []; // Here we store the errors produced by all phase formulas. + let formulasValues = []; // Here we store the values produced by all phase formulas. + + /* We define and evaluate all conditions to be used later during the simulation loop. */ + + conditionsArrayRecord.push(candle.begin); + conditionsArrayRecord.push(candle.end); + + evaluateConditionsAndFormulas(tradingSystem, conditions); + + function evaluateConditionsAndFormulas(tradingSystem, conditions) { + + for (let j = 0; j < tradingSystem.strategies.length; j++) { + + let strategy = tradingSystem.strategies[j]; + + let positionSize = 0 + let positionRate = 0 + + /* Continue with the rest of the formulas and conditions */ + + let triggerStage = strategy.triggerStage + + if (triggerStage !== undefined) { + + if (triggerStage.triggerOn !== undefined) { + + for (let k = 0; k < triggerStage.triggerOn.situations.length; k++) { + + let situation = triggerStage.triggerOn.situations[k]; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'triggerStage' + '-' + 'triggerOn' + '-' + k + '-' + m; + + if (condition.code !== undefined) { + newCondition(key, condition.code); + } + } + } + } + + if (triggerStage.triggerOff !== undefined) { + + for (let k = 0; k < triggerStage.triggerOff.situations.length; k++) { + + let situation = triggerStage.triggerOff.situations[k]; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'triggerStage' + '-' + 'triggerOff' + '-' + k + '-' + m; + + if (condition.code !== undefined) { + newCondition(key, condition.code); + } + } + } + } + + if (triggerStage.takePosition !== undefined) { + + for (let k = 0; k < triggerStage.takePosition.situations.length; k++) { + + let situation = triggerStage.takePosition.situations[k]; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'triggerStage' + '-' + 'takePosition' + '-' + k + '-' + m; + + if (condition.code !== undefined) { + newCondition(key, condition.code); + } + } + } + } + } + + let openStage = strategy.openStage + + if (openStage !== undefined) { + + /* Default Values*/ + if (baseAsset === 'BTC') { + positionSize = balanceAssetA; + positionRate = candle.close; + } else { + positionSize = balanceAssetB; + positionRate = candle.close; + } + + let initialDefinition = openStage.initialDefinition + + if (initialDefinition !== undefined) { + + if (tradePositionSize !== 0) { + positionSize = tradePositionSize + } else { + if (initialDefinition.positionSize !== undefined) { + if (initialDefinition.positionSize.formula !== undefined) { + try { + positionSize = eval(initialDefinition.positionSize.formula.code); + } catch (err) { + initialDefinition.positionSize.formula.error = err.message + } + if (isNaN(positionSize)) { + if (baseAsset === 'BTC') { + positionSize = balanceAssetA; + } else { + positionSize = balanceAssetB; + } + } else { + if (baseAsset === 'BTC') { + if (positionSize > balanceAssetA) { positionSize = balanceAssetA } + } else { + if (positionSize > balanceAssetB) { positionSize = balanceAssetB } + } + } + } + } + } + + if (tradePositionRate !== 0) { + positionRate = tradePositionRate + } else { + if (initialDefinition.positionRate !== undefined) { + if (initialDefinition.positionRate.formula !== undefined) { + try { + positionRate = eval(initialDefinition.positionRate.formula.code); + } catch (err) { + initialDefinition.positionRate.formula.error = err.message + } + if (isNaN(positionRate)) { + if (baseAsset === 'BTC') { + positionRate = candle.close; + } else { + positionRate = candle.close; + } + } + } + } + } + + if (initialDefinition.stopLoss !== undefined) { + + for (let p = 0; p < initialDefinition.stopLoss.phases.length; p++) { + + let phase = initialDefinition.stopLoss.phases[p]; + + /* Evaluate Formula */ + let formulaValue + let formulaError = '' + + if (phase.formula !== undefined) { + try { + formulaValue = eval(phase.formula.code); + if (formulaValue === Infinity) { + formulaError = "Formula evaluates to Infinity." + formulaValue = MAX_STOP_LOSS_VALUE + } + } catch (err) { + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } + } + if (isNaN(formulaValue)) { formulaValue = 0; } + if (formulaValue < MIN_STOP_LOSS_VALUE) { + formulaValue = MIN_STOP_LOSS_VALUE + } + + formulasErrors.push('"' + formulaError + '"') + formulasValues.push(formulaValue) + let key = j + '-' + 'openStage' + '-' + 'initialDefinition' + '-' + 'stopLoss' + '-' + p; + formulas.set(key, formulaValue) + } + + /* next phase event */ + let nextPhaseEvent = phase.nextPhaseEvent; + if (nextPhaseEvent !== undefined) { + + for (let k = 0; k < nextPhaseEvent.situations.length; k++) { + + let situation = nextPhaseEvent.situations[k]; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'openStage' + '-' + 'initialDefinition' + '-' + 'stopLoss' + '-' + p + '-' + k + '-' + m; + + if (condition.code !== undefined) { + newCondition(key, condition.code); + } + } + } + } + } + } + + if (initialDefinition.takeProfit !== undefined) { + + for (let p = 0; p < initialDefinition.takeProfit.phases.length; p++) { + + let phase = initialDefinition.takeProfit.phases[p]; + + /* Evaluate Formula */ + let formulaValue + let formulaError = '' + + if (phase.formula !== undefined) { + try { + formulaValue = eval(phase.formula.code); + if (formulaValue === Infinity) { + formulaError = "Formula evaluates to Infinity." + formulaValue = MAX_TAKE_PROFIT_VALUE + } + } catch (err) { + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } + } + if (isNaN(formulaValue)) { formulaValue = 0; } + if (formulaValue < MIN_TAKE_PROFIT_VALUE) { + formulaValue = MIN_TAKE_PROFIT_VALUE + } + + formulasErrors.push('"' + formulaError + '"') + formulasValues.push(formulaValue) + let key = j + '-' + 'openStage' + '-' + 'initialDefinition' + '-' + 'takeProfit' + '-' + p; + formulas.set(key, formulaValue) + } + + /* next phase event */ + let nextPhaseEvent = phase.nextPhaseEvent; + if (nextPhaseEvent !== undefined) { + + for (let k = 0; k < nextPhaseEvent.situations.length; k++) { + + let situation = nextPhaseEvent.situations[k]; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'openStage' + '-' + 'initialDefinition' + '-' + 'takeProfit' + '-' + p + '-' + k + '-' + m; + + if (condition.code !== undefined) { + newCondition(key, condition.code); + } + } + } + } + } + } + } + + strategy.positionSize = positionSize + strategy.positionRate = positionRate + } + + let manageStage = strategy.manageStage + + if (manageStage !== undefined) { + + if (manageStage.stopLoss !== undefined) { + + for (let p = 0; p < manageStage.stopLoss.phases.length; p++) { + + let phase = manageStage.stopLoss.phases[p]; + + /* Evaluate Formula */ + let formulaValue + let formulaError = '' + + if (phase.formula !== undefined) { + try { + formulaValue = eval(phase.formula.code); + if (formulaValue === Infinity) { + formulaError = "Formula evaluates to Infinity." + formulaValue = MAX_STOP_LOSS_VALUE + } + } catch (err) { + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } + } + if (isNaN(formulaValue)) { formulaValue = 0; } + if (formulaValue < MIN_STOP_LOSS_VALUE) { + formulaValue = MIN_STOP_LOSS_VALUE + } + + formulasErrors.push('"' + formulaError + '"') + formulasValues.push(formulaValue) + let key = j + '-' + 'manageStage' + '-' + 'stopLoss' + '-' + p; + formulas.set(key, formulaValue) + } + + /* next phase event */ + let nextPhaseEvent = phase.nextPhaseEvent; + if (nextPhaseEvent !== undefined) { + + for (let k = 0; k < nextPhaseEvent.situations.length; k++) { + + let situation = nextPhaseEvent.situations[k]; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'manageStage' + '-' + 'stopLoss' + '-' + p + '-' + k + '-' + m; + + if (condition.code !== undefined) { + newCondition(key, condition.code); + } + } + } + } + } + } + + if (manageStage.takeProfit !== undefined) { + + for (let p = 0; p < manageStage.takeProfit.phases.length; p++) { + + let phase = manageStage.takeProfit.phases[p]; + + /* Evaluate Formula */ + let formulaValue + let formulaError = '' + + if (phase.formula !== undefined) { + try { + formulaValue = eval(phase.formula.code); + if (formulaValue === Infinity) { + formulaError = "Formula evaluates to Infinity." + formulaValue = MAX_TAKE_PROFIT_VALUE + } + } catch (err) { + if (phase.formula.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + formulaError = err.message + } + } + if (isNaN(formulaValue)) { formulaValue = 0; } + if (formulaValue < MIN_TAKE_PROFIT_VALUE) { + formulaValue = MIN_TAKE_PROFIT_VALUE + } + + formulasErrors.push('"' + formulaError + '"') + formulasValues.push(formulaValue) + let key = j + '-' + 'manageStage' + '-' + 'takeProfit' + '-' + p; + formulas.set(key, formulaValue) + } + + /* next phase event */ + let nextPhaseEvent = phase.nextPhaseEvent; + if (nextPhaseEvent !== undefined) { + + for (let k = 0; k < nextPhaseEvent.situations.length; k++) { + + let situation = nextPhaseEvent.situations[k]; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'manageStage' + '-' + 'takeProfit' + '-' + p + '-' + k + '-' + m; + + if (condition.code !== undefined) { + newCondition(key, condition.code); + } + } + } + } + } + } + } + + function newCondition(key, node) { + + let condition; + let error = '' + let value + + try { + value = eval(node.code); + } catch (err) { + /* + One possible error is that the conditions references a .previous that is undefined. For this + reason and others, we will simply set the value to false. + */ + value = false + + if (node.code.indexOf('previous') > 0 && err.message.indexOf('of undefined') > 0) { + /* + We are not going to set an error for the casess we are using previous and the error is that the indicator is undefined. + */ + } else { + node.error = err.message + } + } + + condition = { + key: key, + value: value + }; + + conditions.set(condition.key, condition); + + if (condition.value) { + conditionsArrayValues.push(1); + } else { + conditionsArrayValues.push(0); + } + } + } + } + + /* Trigger On Conditions */ + if ( + strategyStage === 'No Stage' && + currentStrategyIndex === -1 + ) { + let minimumBalance + let maximumBalance + let balance + + if (baseAsset === 'BTC') { + balance = balanceAssetA + minimumBalance = minimumBalanceA + maximumBalance = maximumBalanceA + } else { + balance = balanceAssetB + minimumBalance = minimumBalanceB + maximumBalance = maximumBalanceB + } + + if (balance > minimumBalance && balance < maximumBalance) { + + /* + Here we need to pick a strategy, or if there is not suitable strategy for the current + market conditions, we pass until the next period. + + To pick a new strategy we will evaluate what we call the trigger on. Once we enter + into one strategy, we will ignore market conditions for others. However there is also + a strategy trigger off which can be hit before taking a position. If hit, we would + be outside a strategy again and looking for the condition to enter all over again. + + */ + + for (let j = 0; j < tradingSystem.strategies.length; j++) { + + let strategy = tradingSystem.strategies[j]; + + let triggerStage = strategy.triggerStage + + if (triggerStage !== undefined) { + + if (triggerStage.triggerOn !== undefined) { + + for (let k = 0; k < triggerStage.triggerOn.situations.length; k++) { + + let situation = triggerStage.triggerOn.situations[k]; + let passed = true; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + 'triggerStage' + '-' + 'triggerOn' + '-' + k + '-' + m; + + let value = false + if (conditions.get(key) !== undefined) { + value = conditions.get(key).value; + } + + if (value === false) { passed = false; } + } + + if (passed) { + + strategyStage = 'Trigger Stage'; + currentStrategyIndex = j; + currentStrategy.begin = candle.begin; + currentStrategy.beginRate = candle.min; + currentStrategy.endRate = candle.min; // In case the strategy does not get exited + break; + } + } + } + } + } + } else { + let stopRunningDate = new Date(candle.begin) + if (balance < minimumBalance) { + tradingSystem.error = "Min Balance @ " + stopRunningDate.toUTCString() + } + if (balance > maximumBalance) { + tradingSystem.error = "Max Balance @ " + stopRunningDate.toUTCString() + } + } + } + + /* Trigger Off Condition */ + if (strategyStage === 'Trigger Stage') { + + let strategy = tradingSystem.strategies[currentStrategyIndex]; + + let triggerStage = strategy.triggerStage + + if (triggerStage !== undefined) { + + if (triggerStage.triggerOff !== undefined) { + + for (let k = 0; k < triggerStage.triggerOff.situations.length; k++) { + + let situation = triggerStage.triggerOff.situations[k]; + let passed = true; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = currentStrategyIndex + '-' + 'triggerStage' + '-' + 'triggerOff' + '-' + k + '-' + m; + + let value = false + if (conditions.get(key) !== undefined) { + value = conditions.get(key).value; + } + + if (value === false) { passed = false; } + } + + if (passed) { + + currentStrategy.number = currentStrategyIndex + currentStrategy.end = candle.end; + currentStrategy.endRate = candle.min; + currentStrategy.status = 1; + strategyStage = 'No Stage'; + currentStrategyIndex = -1; + break; + } + } + } + } + } + + /* Take Position Condition */ + if (strategyStage === 'Trigger Stage') { + + let strategy = tradingSystem.strategies[currentStrategyIndex]; + + let triggerStage = strategy.triggerStage + + if (triggerStage !== undefined) { + + if (triggerStage.takePosition !== undefined) { + + for (let k = 0; k < triggerStage.takePosition.situations.length; k++) { + + let situation = triggerStage.takePosition.situations[k]; + let passed = true; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = currentStrategyIndex + '-' + 'triggerStage' + '-' + 'takePosition' + '-' + k + '-' + m; + + let value = false + if (conditions.get(key) !== undefined) { + value = conditions.get(key).value; + } + + if (value === false) { passed = false; } + } + + if (passed) { + + type = '"Take Position"'; + + strategyStage = 'Open Stage'; + stopLossStage = 'Open Stage'; + takeProfitStage = 'Open Stage'; + stopLossPhase = 1; + takeProfitPhase = 1; + currentTrade.begin = candle.begin; + currentTrade.beginRate = candle.close; + takePositionNow = true + break; + } + } + } + } + } + + /* Stop Loss Management */ + if ( + (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') && + takePositionNow !== true + ) { + + checkStopPhases() + calculateStopLoss(); + + } + + function checkStopPhases() { + + let strategy = tradingSystem.strategies[currentStrategyIndex]; + + let openStage = strategy.openStage + let manageStage = strategy.manageStage + let parentNode + let j = currentStrategyIndex + let stageKey + let initialDefinitionKey = '' + let p + + if (stopLossStage === 'Open Stage' && openStage !== undefined) { + if (openStage.initialDefinition !== undefined) { + if (openStage.initialDefinition.stopLoss !== undefined) { + parentNode = openStage.initialDefinition + initialDefinitionKey = '-' + 'initialDefinition' + stageKey = 'openStage' + p = stopLossPhase - 1 + } + } + } + + if (stopLossStage === 'Manage Stage' && manageStage !== undefined) { + if (manageStage.stopLoss !== undefined) { + parentNode = manageStage + stageKey = 'manageStage' + p = stopLossPhase - 2 + } + } + + let phase = parentNode.stopLoss.phases[p]; + + let nextPhaseEvent = phase.nextPhaseEvent; + if (nextPhaseEvent !== undefined) { + + for (let k = 0; k < nextPhaseEvent.situations.length; k++) { + + let situation = nextPhaseEvent.situations[k]; + let passed = true; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + stageKey + initialDefinitionKey + '-' + 'stopLoss' + '-' + p + '-' + k + '-' + m; + + let value = false + if (conditions.get(key) !== undefined) { + value = conditions.get(key).value; + } + + if (value === false) { passed = false; } + } + + if (passed) { + + stopLossPhase++; + stopLossStage = 'Manage Stage' + if (takeProfitPhase > 1) { strategyStage = 'Manage Stage' } + return; + } + } + } + } + + function calculateStopLoss() { + + let strategy = tradingSystem.strategies[currentStrategyIndex]; + let openStage = strategy.openStage + let manageStage = strategy.manageStage + let phase + let key + + if (stopLossStage === 'Open Stage' && openStage !== undefined) { + if (openStage.initialDefinition !== undefined) { + if (openStage.initialDefinition.stopLoss !== undefined) { + phase = openStage.initialDefinition.stopLoss.phases[stopLossPhase - 1]; + key = currentStrategyIndex + '-' + 'openStage' + '-' + 'initialDefinition' + '-' + 'stopLoss' + '-' + (stopLossPhase - 1); + } + } + } + + if (stopLossStage === 'Manage Stage' && manageStage !== undefined) { + if (manageStage.stopLoss !== undefined) { + phase = manageStage.stopLoss.phases[stopLossPhase - 2]; + key = currentStrategyIndex + '-' + 'manageStage' + '-' + 'stopLoss' + '-' + (stopLossPhase - 2); + } + } + + if (phase !== undefined) { + if (phase.formula !== undefined) { + stopLoss = formulas.get(key) + } + } + } + + /* Take Profit Management */ + if ( + (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') && + takePositionNow !== true + ) { + + checkTakeProfitPhases(); + calculateTakeProfit(); + + } + + function checkTakeProfitPhases() { + + let strategy = tradingSystem.strategies[currentStrategyIndex]; + + let openStage = strategy.openStage + let manageStage = strategy.manageStage + let parentNode + let j = currentStrategyIndex + let stageKey + let initialDefinitionKey = '' + let p + + if (takeProfitStage === 'Open Stage' && openStage !== undefined) { + if (openStage.initialDefinition !== undefined) { + if (openStage.initialDefinition.takeProfit !== undefined) { + parentNode = openStage.initialDefinition + initialDefinitionKey = '-' + 'initialDefinition' + stageKey = 'openStage' + p = takeProfitPhase - 1 + } + } + } + + if (takeProfitStage === 'Manage Stage' && manageStage !== undefined) { + if (manageStage.takeProfit !== undefined) { + parentNode = manageStage + stageKey = 'manageStage' + p = takeProfitPhase - 2 + } + } + + let phase = parentNode.takeProfit.phases[p]; + + let nextPhaseEvent = phase.nextPhaseEvent; + if (nextPhaseEvent !== undefined) { + + for (let k = 0; k < nextPhaseEvent.situations.length; k++) { + + let situation = nextPhaseEvent.situations[k]; + let passed = true; + + for (let m = 0; m < situation.conditions.length; m++) { + + let condition = situation.conditions[m]; + let key = j + '-' + stageKey + initialDefinitionKey + '-' + 'takeProfit' + '-' + p + '-' + k + '-' + m; + + let value = false + if (conditions.get(key) !== undefined) { + value = conditions.get(key).value; + } + + if (value === false) { passed = false; } + } + + if (passed) { + + takeProfitPhase++; + takeProfitStage = 'Manage Stage' + if (stopLossPhase > 1) { strategyStage = 'Manage Stage' } + return; + } + } + } + } + + function calculateTakeProfit() { + + let strategy = tradingSystem.strategies[currentStrategyIndex]; + let openStage = strategy.openStage + let manageStage = strategy.manageStage + let phase + let key + + if (takeProfitStage === 'Open Stage' && openStage !== undefined) { + if (openStage.initialDefinition !== undefined) { + if (openStage.initialDefinition.takeProfit !== undefined) { + phase = openStage.initialDefinition.takeProfit.phases[takeProfitPhase - 1]; + key = currentStrategyIndex + '-' + 'openStage' + '-' + 'initialDefinition' + '-' + 'takeProfit' + '-' + (takeProfitPhase - 1); + } + } + } + + if (takeProfitStage === 'Manage Stage' && manageStage !== undefined) { + if (manageStage.takeProfit !== undefined) { + phase = manageStage.takeProfit.phases[takeProfitPhase - 2]; + key = currentStrategyIndex + '-' + 'manageStage' + '-' + 'takeProfit' + '-' + (takeProfitPhase - 2); + } + } + + if (phase !== undefined) { + if (phase.formula !== undefined) { + takeProfit = formulas.get(key) + } + } + } + + /* Checking if Stop or Take Profit were hit */ + if ( + (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') && + takePositionNow !== true + ) { + let strategy = tradingSystem.strategies[currentStrategyIndex]; + + /* Checking what happened since the last execution. We need to know if the Stop Loss + or our Take Profit were hit. */ + + /* Stop Loss condition: Here we verify if the Stop Loss was hitted or not. */ + + if ((baseAsset === 'BTC' && candle.max >= stopLoss) || (baseAsset !== 'BTC' && candle.min <= stopLoss)) { + + if (baseAsset === 'BTC') { + strategy.positionSize = balanceAssetB / stopLoss; + strategy.positionRate = stopLoss; + + balanceAssetA = balanceAssetA + balanceAssetB / stopLoss; + balanceAssetB = 0; + } else { + strategy.positionSize = balanceAssetA * stopLoss; + strategy.positionRate = stopLoss; + + balanceAssetB = balanceAssetB + balanceAssetA * stopLoss; + balanceAssetA = 0; + } + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.balanceAssetA = balanceAssetA; + yesterday.balanceAssetB = balanceAssetB; + } + } + + marketRate = stopLoss; + type = '"Close@StopLoss"'; + strategyStage = 'Close Stage'; + stopLossStage = 'No Stage'; + takeProfitStage = 'No Stage'; + currentTrade.end = candle.end; + currentTrade.status = 1; + currentTrade.exitType = 1; + currentTrade.endRate = stopLoss; + + currentStrategy.number = currentStrategyIndex + currentStrategy.end = candle.end; + currentStrategy.endRate = candle.min; + currentStrategy.status = 1; + } + + /* Take Profit condition: Here we verify if the Take Profit was filled or not. */ + + if ((baseAsset === 'BTC' && candle.min <= takeProfit) || (baseAsset !== 'BTC' && candle.max >= takeProfit)) { + + if (baseAsset === 'BTC') { + strategy.positionSize = balanceAssetB / takeProfit; + strategy.positionRate = takeProfit; + + balanceAssetA = balanceAssetA + balanceAssetB / takeProfit; + balanceAssetB = 0; + } else { + strategy.positionSize = balanceAssetA * takeProfit; + strategy.positionRate = takeProfit; + + balanceAssetB = balanceAssetB + balanceAssetA * takeProfit; + balanceAssetA = 0; + } + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.balanceAssetA = balanceAssetA; + yesterday.balanceAssetB = balanceAssetB; + + } + } + + marketRate = takeProfit; + type = '"Close@TakeProfit"'; + strategyStage = 'Close Stage'; + stopLossStage = 'No Stage'; + takeProfitStage = 'No Stage'; + currentTrade.end = candle.end; + currentTrade.status = 1; + currentTrade.exitType = 2; + currentTrade.endRate = takeProfit; + + currentStrategy.number = currentStrategyIndex + currentStrategy.end = candle.end; + currentStrategy.endRate = candle.min; + currentStrategy.status = 1; + } + } + + /* Taking a Position */ + if ( + takePositionNow === true + ) { + takePositionNow = false + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> takePositionNow -> Entering code block."); } + + /* Position size and rate */ + let strategy = tradingSystem.strategies[currentStrategyIndex]; + + tradePositionSize = strategy.positionSize; + tradePositionRate = strategy.positionRate; + + /* We see if we need to put the actual order at the exchange. */ + + if (interExecutionMemory.executionContext !== undefined) { + switch (interExecutionMemory.executionContext.status) { + case "Without a Position": { // We need to put the order because It was not put yet. + if (strategy.openStage !== undefined) { + if (strategy.openStage.openExecution !== undefined) { + putOpeningOrder() + return + } + } + break + } + case "Position Closed": { // Waiting for a confirmation that the position was closed. + if (strategy.openStage !== undefined) { + if (strategy.openStage.openExecution !== undefined) { + putOpeningOrder() + return + } + } + break + } + case "Taking Position": { // Waiting for a confirmation that the position was taken. + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> takePositionNow -> Exiting code block because status is Taking Position."); } + break + } + case "In a Position": { // This should mean that we already put the order at the exchange. + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> takePositionNow -> Exiting code block because status is In a Position."); } + break + } + } + } else { // The context does not exist so it means we are not in a position. + if (strategy.openStage !== undefined) { + if (strategy.openStage.openExecution !== undefined) { + putOpeningOrder() + return + } + } + } + + takePositionAtSimulation() + return + + function putOpeningOrder() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Entering function."); } + + /* We wont take a position unless we are withing the startDate and the endDate range */ + if (startDate !== undefined) { + if (candle.begin < startDate.valueOf()) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because current candle begins before the start date. -> startDate = " + startDate); } + takePositionAtSimulation() + return; + } + } + + /* This validation is disbled for now because we do not have the correct end date at this point. + if (endDate !== undefined) { + if (candle.begin > endDate.valueOf()) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because current candle begins after the end date. -> endDate = " + endDate); } + takePositionAtSimulation() + return; + } + } + */ + + /* Checking the status of current positions */ + let positions = assistant.getPositions(); + if (positions.length > 0) { + let position = positions[positions.length - 1] // We are allways checking the the last position is not open. + if (position.status === 'open') { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because the last position is still open. "); } + afterLoop(); + return + } + } + + /* Mechanism to avoid putting the same order over and over again at different executions of the simulation engine. */ + + if (interExecutionMemory.executionContext !== undefined) { + if (interExecutionMemory.executionContext.periods !== undefined) { + if (periods <= interExecutionMemory.executionContext.periods) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because it was already placed at a previous execution." ); } + takePositionAtSimulation() + return; + } + } + } + + /* We are not going to place orders based on outdated information. The next filter prevents firing orders when backtesting. */ + let today = new Date(Math.trunc((new Date().valueOf()) / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS) + let processDay = new Date(Math.trunc(currentDay.valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS) + if (today.valueOf() !== processDay.valueOf()) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Not placing the trade at the exchange because the current candle belongs to the previous day and that is considered simulation and not live trading."); } + takePositionAtSimulation() + return; + } + + let openPositionRate + let amountA + let amountB + let positionDirection + + if (baseAsset === 'BTC') { + positionDirection = "sell" + + openPositionRate = tradePositionRate - 100 // Provisional stuff to simulate a market order. Put the price lower to get it executed quickly + + amountA = tradePositionSize * openPositionRate + amountB = tradePositionSize + } else { + positionDirection = "buy" + + openPositionRate = tradePositionRate + 100 // Provisional stuff to simulate a market order. Put the price higher to get it executed quickly + + amountA = tradePositionSize + amountB = tradePositionSize / openPositionRate + } + + interExecutionMemory.executionContext = { + status: "Taking Position" + } + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> Ready to put order."); } + assistant.putPosition(positionDirection, openPositionRate, amountA, amountB, onOrderPut) + + function onOrderPut(err) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> Entering function."); } + + try { + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); } + interExecutionMemory.executionContext = { + status: "In a Position", + periods: periods, + amountA: amountA, + amountB: amountB + } + takePositionAtSimulation() + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); } + strategy.openStage.openExecution.error = err.message + afterLoop() + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); } + strategy.openStage.openExecution.error = err.message + afterLoop() + return; + } + } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> putOpeningOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); } + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] runSimulation -> putOpeningOrder -> onOrderPut -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return + } + } + } + + function takePositionAtSimulation() { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> takePositionAtSimulation -> Entering function."); } + + /* Continue with the simulation */ + + calculateTakeProfit(); + calculateStopLoss(); + + marketRate = candle.close; + + previousBalanceAssetA = balanceAssetA; + previousBalanceAssetB = balanceAssetB; + + lastTradeProfitLoss = 0; + lastTradeROI = 0; + + if (baseAsset === 'BTC') { + balanceAssetB = balanceAssetB + tradePositionSize * tradePositionRate; + balanceAssetA = balanceAssetA - tradePositionSize; + } else { + balanceAssetA = balanceAssetA + tradePositionSize / tradePositionRate; + balanceAssetB = balanceAssetB - tradePositionSize; + } + + positionInstant = candle.end; + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.balanceAssetA = balanceAssetA; + yesterday.balanceAssetB = balanceAssetB; + + yesterday.lastTradeProfitLoss = lastTradeProfitLoss; + yesterday.lastTradeROI = lastTradeROI; + } + } + + addRecord(); + controlLoop(); + return + } + } + + /* Closing a Position */ + if (strategyStage === 'Close Stage') { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Closing a Position -> Entering code block."); } + + /* Position size and rate */ + let strategy = tradingSystem.strategies[currentStrategyIndex]; + + /* We see if we need to put the actual order at the exchange. */ + + if (interExecutionMemory.executionContext !== undefined) { + switch (interExecutionMemory.executionContext.status) { + case "Without a Position": { // No way to close anything at the exchange. + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Closing a Position -> Exiting code block because status is Without a Position."); } + break + } + case "In a Position": { // This should mean that we already put the order at the exchange. + if (strategy.closeStage !== undefined) { + if (strategy.closeStage.closeExecution !== undefined) { + putClosingOrder() + return + } + } + break + } + case "Closing Position": { // Waiting for a confirmation that the position was taken. + if (strategy.closeStage !== undefined) { + if (strategy.closeStage.closeExecution !== undefined) { + putClosingOrder() + return + } + } + break + } + + case "Position Closed": { // + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Closing a Position -> Exiting code block because status is Position Closed."); } + break + } + } + } + + closePositionAtSimulation() + return + + function putClosingOrder() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> Entering function."); } + + /* Checking the status of current positions */ + let positions = assistant.getPositions(); + if (positions.length > 0) { + let position = positions[positions.length - 1] // We are allways checking the the last position is not open. + if (position.status === 'open') { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> Exiting function because status of last position is Open."); } + afterLoop(); + return + } + } + + /* Mechanism to avoid putting the same order over and over again at different executions of the simulation engine. */ + + if (interExecutionMemory.executionContext !== undefined) { + if (interExecutionMemory.executionContext.periods !== undefined) { + if (periods <= interExecutionMemory.executionContext.periods) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> Exiting function because this closing was already submited at a previous execution."); } + closePositionAtSimulation() + return; + } + } + } + + let closePositionRate + let amountA + let amountB + let positionDirection + + if (baseAsset === 'BTC') { + positionDirection = "buy" + + closePositionRate = ticker.last + 100; // This is provisional and totally arbitrary, until we have a formula on the designer that defines this stuff. + + amountA = interExecutionMemory.executionContext.amountA + amountB = interExecutionMemory.executionContext.amountA / closePositionRate + } else { + positionDirection = "sell" + + closePositionRate = ticker.last - 100; // This is provisional and totally arbitrary, until we have a formula on the designer that defines this stuff. + + amountA = interExecutionMemory.executionContext.amountB * closePositionRate + amountB = interExecutionMemory.executionContext.amountB + } + + interExecutionMemory.executionContext = { + status: "Closing Position" + } + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> About to close position at the exchange."); } + assistant.putPosition(positionDirection, closePositionRate, amountA, amountB, onOrderPut) + + function onOrderPut(err) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> onOrderPut -> Entering function."); } + + try { + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> onOrderPut -> DEFAULT_OK_RESPONSE "); } + interExecutionMemory.executionContext = { + status: "Position Closed", + periods: periods, + amountA: amountA, + amountB: amountB + } + closePositionAtSimulation() + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putClosingOrder -> onOrderPut -> DEFAULT_FAIL_RESPONSE "); } + /* We will assume that the problem is temporary, and expect that it will work at the next execution.*/ + strategy.closeStage.closeExecution.error = err.message + afterLoop() + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> putOpeningOrder -> onOrderPut -> DEFAULT_RETRY_RESPONSE "); } + strategy.closeStage.closeExecution.error = err.message + afterLoop() + return; + } + } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[ERROR] runSimulation -> putClosingOrder -> onOrderPut -> Unexpected Response -> Message = " + err.message); } + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] runSimulation -> putClosingOrder -> onOrderPut -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return + } + } + } + + function closePositionAtSimulation() { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> closePositionAtSimulation -> Entering function."); } + + roundtrips++; + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.Roundtrips++; + } + } + + if (baseAsset === 'BTC') { + lastTradeProfitLoss = balanceAssetA - previousBalanceAssetA; + lastTradeROI = lastTradeProfitLoss * 100 / tradePositionSize; + if (isNaN(lastTradeROI)) { lastTradeROI = 0; } + profit = balanceAssetA - initialBalanceA; + } else { + lastTradeProfitLoss = balanceAssetB - previousBalanceAssetB; + lastTradeROI = lastTradeProfitLoss * 100 / tradePositionSize; + if (isNaN(lastTradeROI)) { lastTradeROI = 0; } + profit = balanceAssetB - initialBalanceB; + } + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.lastTradeProfitLoss = lastTradeProfitLoss; + yesterday.profit = profit; + yesterday.lastTradeROI = lastTradeROI; + } + } + + currentTrade.lastTradeROI = lastTradeROI; + currentTrade.stopRate = stopLoss; + + if (lastTradeProfitLoss > 0) { + hits++; + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.hits++; + } + } + + } else { + fails++; + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.fails++; + } + } + } + + if (baseAsset === 'BTC') { + ROI = (initialBalanceA + profit) / initialBalanceA - 1; + hitRatio = hits / roundtrips; + anualizedRateOfReturn = ROI / days * 365; + } else { + ROI = (initialBalanceB + profit) / initialBalanceB - 1; + hitRatio = hits / roundtrips; + anualizedRateOfReturn = ROI / days * 365; + } + + if (currentDay !== undefined) { + if (positionInstant < currentDay.valueOf()) { + yesterday.ROI = ROI; + yesterday.hitRatio = hitRatio; + yesterday.anualizedRateOfReturn = anualizedRateOfReturn; + } + } + + addRecord(); + + currentStrategyIndex = -1; + stopLoss = 0; + tradePositionRate = 0; + tradePositionSize = 0; + positionInstant = undefined; + takeProfit = 0; + strategyStage = 'No Stage'; + stopLossStage = 'No Stage'; + takeProfitStage = 'No Stage'; + stopLossPhase = 0; + takeProfitPhase = 0; + controlLoop(); + return + } + } + + /* Not a buy or sell condition */ + + marketRate = candle.close; + addRecord(); + controlLoop(); + return + + function addRecord() { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> addRecord -> Entering function."); } + + // Since we are going to write the message to a file that the Simulation Executor is going to read, we use the abbreviations. + let messageType; + let message; + let simulationRecord; + let executionRecord; + let executionMessage; + + messageId++; + + if (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage' || type === '"Close@TakeProfit"' || type === '"Close@StopLoss"') { + + if (type === '"Take Position"') { + messageType = MESSAGE_TYPE.Order; + orderId++; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> addRecord -> Taking Position Now. "); } + + } else { + if (type === '"Close@TakeProfit"' || type === '"Close@StopLoss"') { + messageType = MESSAGE_TYPE.OrderClose; + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> addRecord -> Closing Position Now. "); } + + } else { + messageType = MESSAGE_TYPE.OrderUpdate; + } + } + + let exitOutcome = "" + if (messageType === MESSAGE_TYPE.OrderClose && type === '"Close@TakeProfit"') { + exitOutcome = "TP" + } + if (messageType === MESSAGE_TYPE.OrderClose && type === '"Close@StopLoss"') { + exitOutcome = "SL" + } + + executionMessage = createMessage( + messageId, + MESSAGE_ENTITY.SimulationEngine, + MESSAGE_ENTITY.SimulationExecutor, + messageType, + (new Date()).valueOf(), + orderId.toString(), + ORDER_CREATOR.SimulationEngine, + (new Date()).valueOf(), + ORDER_OWNER.User, + global.EXCHANGE_NAME, + "BTC_USDT", + 0, + ORDER_TYPE.Limit, + tradePositionRate, + stopLoss, + takeProfit, + ORDER_DIRECTION.Sell, + -1, + ORDER_STATUS.Signaled, + 0, + exitOutcome, + "") + + } + else { + + executionMessage = createMessage( + messageId, + MESSAGE_ENTITY.SimulationEngine, + MESSAGE_ENTITY.SimulationExecutor, + MESSAGE_TYPE.HeartBeat, + (new Date()).valueOf(), + "", + "", + 0, + "", + "", + "", + 0, + "", + 0, + 0, + 0, + "", + 0, + "", + 0, + "", + "") + } + + executionRecord = { + begin: candle.begin, + end: candle.end, + executionRecord: executionMessage + } + + executionArray.push(executionRecord) + + let strategyStageNumber + switch (strategyStage) { + case 'No Stage': { + strategyStageNumber = 0 + break + } + case 'Trigger Stage': { + strategyStageNumber = 1 + break + } + case 'Open Stage': { + strategyStageNumber = 2 + break + } + case 'Manage Stage': { + strategyStageNumber = 3 + break + } + case 'Close Stage': { + strategyStageNumber = 4 + break + } + } + + if (balanceAssetA === Infinity) { + balanceAssetA = Number.MAX_SAFE_INTEGER + } + + if (balanceAssetB === Infinity) { + balanceAssetB = Number.MAX_SAFE_INTEGER + } + + let quotedBaseAsset = '"' + baseAsset + '"' + + simulationRecord = { + begin: candle.begin, + end: candle.end, + type: type, + marketRate: marketRate, + amount: 1, + balanceA: balanceAssetA, + balanceB: balanceAssetB, + profit: profit, + lastTradeProfitLoss: lastTradeProfitLoss, + stopLoss: stopLoss, + roundtrips: roundtrips, + hits: hits, + fails: fails, + hitRatio: hitRatio, + ROI: ROI, + periods: periods, + days: days, + anualizedRateOfReturn: anualizedRateOfReturn, + positionRate: tradePositionRate, + lastTradeROI: lastTradeROI, + strategy: currentStrategyIndex, + strategyStageNumber: strategyStageNumber, + takeProfit: takeProfit, + stopLossPhase: stopLossPhase, + takeProfitPhase: takeProfitPhase, + executionRecord: executionMessage, + positionSize: tradePositionSize, + initialBalanceA: initialBalanceA, + minimumBalanceA: minimumBalanceA, + maximumBalanceA: maximumBalanceA, + initialBalanceB: initialBalanceB, + minimumBalanceB: minimumBalanceB, + maximumBalanceB: maximumBalanceB, + baseAsset: quotedBaseAsset + } + + recordsArray.push(simulationRecord); + + type = '""'; + + /* Prepare the information for the Conditions File */ + + conditionsArrayRecord.push(currentStrategyIndex); + conditionsArrayRecord.push(strategyStageNumber); + conditionsArrayRecord.push(stopLossPhase); + conditionsArrayRecord.push(takeProfitPhase); + conditionsArrayRecord.push(conditionsArrayValues); + conditionsArrayRecord.push(formulasErrors); + conditionsArrayRecord.push(formulasValues); + + conditionsArray.push(conditionsArrayRecord); + + /* Prepare the information for the Strategies File*/ + + if ( + (currentStrategy.begin !== 0 && currentStrategy.end !== 0) || + (currentStrategy.begin !== 0 && i === candles.length - 1 && lastCandle.end !== lastInstantOfTheDay) + ) { + + strategiesArray.push(currentStrategy); + + currentStrategy = { + begin: 0, + end: 0, + status: 0, + number: 0, + beginRate: 0, + endRate: 0 + } + } + + /* Prepare the information for the Trades File */ + + if ( + (currentTrade.begin !== 0 && currentTrade.end !== 0) || + (currentTrade.begin !== 0 && i === candles.length - 1 && lastCandle.end !== lastInstantOfTheDay) + ) { + + currentTrade.profit = lastTradeProfitLoss; + + tradesArray.push(currentTrade); + + currentTrade = { + begin: 0, + end: 0, + status: 0, + lastTradeROI: 0, + exitType: 0, + beginRate: 0, + endRate: 0 + } + } + } + } + + function controlLoop() { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> controlLoop -> Entering function."); } + i++ + if (i < candles.length) { + process.nextTick(loop) + } else { + afterLoop() + } + } + + function afterLoop() { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> afterLoop -> Entering function."); } + + /* + Before returning we need to see if we have to record some of our counters at the interExecutionMemory. + To do that, the condition to be met is that this execution must include all candles of the currentDay. + */ + + if (currentDay !== undefined) { + + if (lastCandle.end === lastInstantOfTheDay) { + + interExecutionMemory.balanceAssetA = yesterday.balanceAssetA; + interExecutionMemory.balanceAssetB = yesterday.balanceAssetB; + interExecutionMemory.lastTradeProfitLoss = yesterday.lastTradeProfitLoss; + interExecutionMemory.profit = yesterday.profit; + interExecutionMemory.lastTradeROI = yesterday.lastTradeROI; + + interExecutionMemory.roundtrips = interExecutionMemory.roundtrips + yesterday.Roundtrips; + interExecutionMemory.fails = interExecutionMemory.fails + yesterday.fails; + interExecutionMemory.hits = interExecutionMemory.hits + yesterday.hits; + interExecutionMemory.periods = interExecutionMemory.periods + yesterday.Periods; + + interExecutionMemory.messageId = interExecutionMemory.messageId + yesterday.messageId; + interExecutionMemory.orderId = interExecutionMemory.orderId + yesterday.orderId; + + interExecutionMemory.hitRatio = yesterday.hitRatio; + interExecutionMemory.ROI = yesterday.ROI; + interExecutionMemory.anualizedRateOfReturn = yesterday.anualizedRateOfReturn; + } + } + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> callback -> recordsArray.length = " + recordsArray.length); } + + callback(tradingSystem, executionArray, recordsArray, conditionsArray, strategiesArray, tradesArray, lastObjectsArray); + } + + + function getElement(pArray, begin, end) { + + let element; + + for (let i = 0; i < pArray.length; i++) { + + element = pArray[i]; + + if (begin >= element.begin && end <= element.end) { + return element + } + } + + return + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] runSimulation -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildLRC(dataFile, callBackFunction) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildLRC -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < dataFile.length; i++) { + + let LRC = { + begin: dataFile[i][0], + end: dataFile[i][1], + _15: dataFile[i][2], + _30: dataFile[i][3], + _60: dataFile[i][4] + }; + + if (previous !== undefined) { + + if (previous._15 > LRC._15) { LRC.direction15 = 'Down'; } + if (previous._15 < LRC._15) { LRC.direction15 = 'Up'; } + if (previous._15 === LRC._15) { LRC.direction15 = 'Side'; } + + if (previous._30 > LRC._30) { LRC.direction30 = 'Down'; } + if (previous._30 < LRC._30) { LRC.direction30 = 'Up'; } + if (previous._30 === LRC._30) { LRC.direction30 = 'Side'; } + + if (previous._60 > LRC._60) { LRC.direction60 = 'Down'; } + if (previous._60 < LRC._60) { LRC.direction60 = 'Up'; } + if (previous._60 === LRC._60) { LRC.direction60 = 'Side'; } + + } + + LRC.previous = previous; + + LRCMap.set(LRC.begin, LRC); + + previous = LRC; + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] buildLRC -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildPercentageBandwidthMap(dataFile, callBackFunction) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildPercentageBandwidthMap -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < dataFile.length; i++) { + + let percentageBandwidth = { + begin: dataFile[i][0], + end: dataFile[i][1], + value: dataFile[i][2], + movingAverage: dataFile[i][3], + bandwidth: dataFile[i][4] + }; + + if (previous !== undefined) { + + if (previous.movingAverage > percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'Down'; } + if (previous.movingAverage < percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'Up'; } + if (previous.movingAverage === percentageBandwidth.movingAverage) { percentageBandwidth.direction = 'Side'; } + + } + + percentageBandwidth.previous = previous; + + percentageBandwidthMap.set(percentageBandwidth.begin, percentageBandwidth); + + previous = percentageBandwidth; + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] buildPercentageBandwidthMap -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildBollingerBandsMap(dataFile, callBackFunction) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildBollingerBandsMap -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < dataFile.length; i++) { + + let bollingerBand = { + begin: dataFile[i][0], + end: dataFile[i][1], + movingAverage: dataFile[i][2], + standardDeviation: dataFile[i][3], + deviation: dataFile[i][4] + }; + + if (previous !== undefined) { + + if (previous.movingAverage > bollingerBand.movingAverage) { bollingerBand.direction = 'Down'; } + if (previous.movingAverage < bollingerBand.movingAverage) { bollingerBand.direction = 'Up'; } + if (previous.movingAverage === bollingerBand.movingAverage) { bollingerBand.direction = 'Side'; } + + } + + bollingerBand.previous = previous; + + bollingerBandsMap.set(bollingerBand.begin, bollingerBand); + + previous = bollingerBand; + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] buildBollingerBandsMap -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildBollingerChannelsArray(dataFile, callBackFunction) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildBollingerChannelsArray -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < dataFile.length; i++) { + + let bollingerChannel = { + begin: dataFile[i][0], + end: dataFile[i][1], + direction: dataFile[i][2], + period: dataFile[i][3] + }; + + bollingerChannel.previous = previous; + + bollingerChannelsArray.push(bollingerChannel); + + previous = bollingerChannel; + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] buildBollingerChannelsArray -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildBollingerSubChannelsArray(dataFile, callBackFunction) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildBollingerSubChannelsArray -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < dataFile.length; i++) { + + let bollingerSubChannel = { + begin: dataFile[i][0], + end: dataFile[i][1], + direction: dataFile[i][2], + slope: dataFile[i][3], + period: dataFile[i][4], + firstMovingAverage: dataFile[i][5], + lastMovingAverage: dataFile[i][6], + firstDeviation: dataFile[i][7], + lastDeviation: dataFile[i][8] + }; + + bollingerSubChannel.previous = previous; + + bollingerSubChannelsArray.push(bollingerSubChannel); + + previous = bollingerSubChannel; + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] buildBollingerSubChannelsArray -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function buildCandles(dataFile, callBackFunction) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildCandles -> Entering function."); } + + try { + + let previous; + + for (let i = 0; i < dataFile.length; i++) { + + let candle = { + open: undefined, + close: undefined, + min: 10000000000000, + max: 0, + begin: undefined, + end: undefined, + direction: undefined + }; + + candle.min = dataFile[i][0]; + candle.max = dataFile[i][1]; + + candle.open = dataFile[i][2]; + candle.close = dataFile[i][3]; + + candle.begin = dataFile[i][4]; + candle.end = dataFile[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'; } + + candle.previous = previous; + + candles.push(candle); + + previous = candle; + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] buildCandles -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } +}; + + + diff --git a/Root.js b/Root.js index d53592834..ff3e8c56f 100644 --- a/Root.js +++ b/Root.js @@ -233,7 +233,7 @@ processConfig.timePeriod = global.EXECUTION_CONFIG.timePeriod } - // TODO Pending. Move this if inside IndicatorBotProcessMainLoop line 270 + if (processConfig.framework !== undefined) { if (processConfig.framework.name === "Multi-Period-Daily" || processConfig.framework.name === "Multi-Period-Market") { processConfig.framework.startDate.resumeExecution = false; diff --git a/Run.js b/Run.js index 3ba0a991d..fac89b6b5 100644 --- a/Run.js +++ b/Run.js @@ -204,20 +204,20 @@ async function readExecutionConfiguration(execution) { } } - if (baseAsset === 'BTC') { - if (receivedParameters.initialBalance !== undefined) { - process.env.INITIAL_BALANCE_ASSET_A = receivedParameters.initialBalance; - process.env.INITIAL_BALANCE_ASSET_B = 0 - } - } else { + if (baseAsset === 'BTC') { // NOTE: POLONIEX, the only exchange working so far, has Asset A and B inverted. We need to fix this. if (receivedParameters.initialBalance !== undefined) { process.env.INITIAL_BALANCE_ASSET_B = receivedParameters.initialBalance; process.env.INITIAL_BALANCE_ASSET_A = 0 + } + } else { + if (receivedParameters.initialBalance !== undefined) { + process.env.INITIAL_BALANCE_ASSET_A = receivedParameters.initialBalance; + process.env.INITIAL_BALANCE_ASSET_B = 0 } } } catch (err) { - process.env.INITIAL_BALANCE_ASSET_A = 0.001 // default - process.env.INITIAL_BALANCE_ASSET_B = 0 // default + process.env.INITIAL_BALANCE_ASSET_A = 0 // default + process.env.INITIAL_BALANCE_ASSET_B = 0.001 // default } } } diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index d43569348..f8b03155b 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -54,8 +54,8 @@ } USER_BOT_MODULE = {} - //USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - USER_BOT_MODULE.newUserBot = eval(text); // Use this for production + USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + //USER_BOT_MODULE.newUserBot = eval(text); // Use this for production filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; filePath += "/Commons.js" @@ -70,8 +70,8 @@ return; } COMMONS_MODULE = {} - //COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - COMMONS_MODULE.newCommons = eval(text); // Use this for production + COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + //COMMONS_MODULE.newCommons = eval(text); // Use this for production callBackFunction(global.DEFAULT_OK_RESPONSE); } diff --git a/User.Bot.js b/User.Bot.js new file mode 100644 index 000000000..ca0130408 --- /dev/null +++ b/User.Bot.js @@ -0,0 +1,556 @@ +exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) { + + const FULL_LOG = true; + const LOG_FILE_CONTENT = false; + + const MODULE_NAME = "User Bot"; + + const EXECUTION_FOLDER_NAME = "Trading-Execution"; + const SIMULATED_RECORDS_FOLDER_NAME = "Trading-Simulation"; + const CONDITIONS_FOLDER_NAME = "Simulation-Conditions"; + const STRATEGIES_FOLDER_NAME = "Simulation-Strategies"; + const TRADES_FOLDER_NAME = "Simulation-Trades"; + + const commons = COMMONS.newCommons(bot, logger, UTILITIES); + + thisObject = { + initialize: initialize, + start: start + }; + + let utilities = UTILITIES.newCloudUtilities(bot, logger); + + let dataDependencies; + let assistant; + + return thisObject; + + function initialize(pDataDependencies, callBackFunction, pAssistant) { + + try { + + logger.fileName = MODULE_NAME; + logger.initialize(); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } + + dataDependencies = pDataDependencies; + assistant = pAssistant; + + callBackFunction(global.DEFAULT_OK_RESPONSE); + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function start(dataFiles, timePeriod, outputPeriodLabel, currentDay, startDate, endDate, interExecutionMemory, callBackFunction) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); } + + let market = global.MARKET; + let dataFile; + + let recordsArray + let conditionsArray + let strategiesArray + let tradesArray + let lastObjectsArray + + let tradingSystem = {}; + + commons.initializeData(); + + for (let i = 0; i < dataDependencies.config.length; i++) { + + let dependency = dataDependencies.config[i]; + dataFile = dataFiles[i]; + + switch (i) { + /* + case 0: { + commons.buildLRC(dataFile, callBackFunction); + break; + }*/ + case 0: { + commons.buildPercentageBandwidthMap(dataFile, callBackFunction); + break; + } + case 1: { + commons.buildBollingerBandsMap(dataFile, callBackFunction); + break; + } + case 2: { + commons.buildBollingerChannelsArray(dataFile, callBackFunction); + break; + } + case 3: { + commons.buildBollingerSubChannelsArray(dataFile, callBackFunction); + break; + } + case 4: { + commons.buildCandles(dataFile, callBackFunction); + break; + } + } + } + + commons.runSimulation( + timePeriod, + currentDay, + startDate, + endDate, + interExecutionMemory, + assistant, + writeFiles, + callBackFunction) + + function writeFiles(pTradingSystem, pExecutionArray, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray, pLastObjectsArray) { + + tradingSystem = pTradingSystem + executionArray = pExecutionArray + recordsArray = pRecordsArray + conditionsArray = pConditionsArray + strategiesArray = pStrategiesArray + tradesArray = pTradesArray + lastObjectsArray = pLastObjectsArray + + writeExecutionFile() + } + + function writeExecutionFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < executionArray.length; i++) { + + let record = executionArray[i]; + + /* Will only add to the file the records of the current day */ + + if (record.begin < currentDay.valueOf()) { continue; } + + fileContent = fileContent + separator + '[' + + record.begin + "," + + record.end + "," + + JSON.stringify(record.executionRecord) + "]"; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + EXECUTION_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + filePath += '/' + fileName + + fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeExecutionFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + writeRecordsFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> onFileCreated -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeExecutionFile -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeRecordsFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeRecordsFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < recordsArray.length; i++) { + + let record = recordsArray[i]; + + /* Will only add to the file the records of the current day */ + + if (record.begin < currentDay.valueOf()) { continue; } + + fileContent = fileContent + separator + '[' + + record.begin + "," + + record.end + "," + + record.type + "," + + record.marketRate + "," + + record.amount + "," + + record.balanceA + "," + + record.balanceB + "," + + record.profit + "," + + record.lastTradeProfitLoss + "," + + record.stopLoss + "," + + record.roundtrips + "," + + record.hits + "," + + record.fails + "," + + record.hitRatio + "," + + record.ROI + "," + + record.periods + "," + + record.days + "," + + record.anualizedRateOfReturn + "," + + record.positionRate + "," + + record.lastTradeROI + "," + + record.strategy + "," + + record.strategyStageNumber + "," + + record.takeProfit + "," + + record.stopLossPhase + "," + + record.takeProfitPhase + "," + + JSON.stringify(record.executionRecord) + "," + + record.positionSize + "," + + record.initialBalanceA + "," + + record.minimumBalanceA + "," + + record.maximumBalanceA + "," + + record.initialBalanceB + "," + + record.minimumBalanceB + "," + + record.maximumBalanceB + "," + + record.baseAsset + "]"; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + filePath += '/' + fileName + + fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeRecordsFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeRecordsFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> writeRecordsFile -> onFileCreated -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> writeRecordsFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> writeRecordsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + writeConditionsFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeRecordsFile -> onFileCreated -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeRecordsFile -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeConditionsFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeConditionsFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < conditionsArray.length; i++) { + + let record = conditionsArray[i]; + + /* Will only add to the file the records of the current day */ + + if (record.begin < currentDay.valueOf()) { continue; } + + let conditions = ""; + let conditionsSeparator = ""; + + /* Will only add to the file the records of the current day */ + + if (record.begin < currentDay.valueOf()) { continue; } + + for (let j = 0; j < record.length - 3; j++) { + conditions = conditions + conditionsSeparator + record[j]; + if (conditionsSeparator === "") { conditionsSeparator = ","; } + } + + conditions = conditions + conditionsSeparator + '[' + record[record.length - 3] + ']'; // The last item contains an Array of condition values. + conditions = conditions + conditionsSeparator + '[' + record[record.length - 2] + ']'; // The last item contains an Array of formulaErrors. + conditions = conditions + conditionsSeparator + '[' + record[record.length - 1] + ']'; // The last item contains an Array of formulaValues. + + fileContent = fileContent + separator + '[' + conditions + ']'; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + fileContent = "[" + JSON.stringify(tradingSystem) + "," + JSON.stringify(lastObjectsArray) + "," + fileContent + "]"; + + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + CONDITIONS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + filePath += '/' + fileName + + fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeConditionsFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeConditionsFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> writeConditionsFile -> onFileCreated -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> writeConditionsFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> writeConditionsFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + writeStrategiesFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeConditionsFile -> onFileCreated -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeConditionsFile -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeStrategiesFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStrategiesFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < strategiesArray.length; i++) { + let record = strategiesArray[i]; + + /* Will only add to the file the records of the current day. In this case since objects can span more than one day, we add all of the objects that ends + at the current date. */ + + if (record.end < currentDay.valueOf()) { continue; } + + fileContent = fileContent + separator + '[' + + record.begin + "," + + record.end + "," + + record.status + "," + + record.number + "," + + record.beginRate + "," + + record.endRate + "]"; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + STRATEGIES_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + filePath += '/' + fileName + + fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStrategiesFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStrategiesFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> writeStrategiesFile -> onFileCreated -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> writeStrategiesFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> writeStrategiesFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + writeTradesFile(); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeStrategiesFile -> onFileCreated -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeStrategiesFile -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function writeTradesFile() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeTradesFile -> Entering function."); } + + let separator = ""; + let fileRecordCounter = 0; + + let fileContent = ""; + + for (let i = 0; i < tradesArray.length; i++) { + + let record = tradesArray[i]; + + /* Will only add to the file the records of the current day. In this case since objects can span more than one day, we add all of the objects that ends + at the current date. */ + + if (record.end < currentDay.valueOf()) { continue; } + if (record.stopRate === undefined) { record.stopRate = 0} + + fileContent = fileContent + separator + '[' + + record.begin + "," + + record.end + "," + + record.status + "," + + record.lastTradeROI + "," + + record.beginRate + "," + + record.endRate + "," + + record.exitType + "," + + record.stopRate + "]"; + + if (separator === "") { separator = ","; } + + fileRecordCounter++; + + } + + fileContent = "[" + fileContent + "]"; + + let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2); + let fileName = '' + market.assetA + '_' + market.assetB + '.json'; + + let filePathRoot = bot.devTeam + "/" + bot.codeName + "." + bot.version.major + "." + bot.version.minor + "/" + global.CLONE_EXECUTOR.codeName + "." + global.CLONE_EXECUTOR.version + "/" + global.EXCHANGE_NAME + "/" + bot.dataSetVersion; + let filePath = filePathRoot + "/Output/" + TRADES_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + outputPeriodLabel + "/" + dateForPath; + filePath += '/' + fileName + + fileStorage.createTextFile(bot.devTeam, filePath, fileContent + '\n', onFileCreated); + + function onFileCreated(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeTradesFile -> onFileCreated -> Entering function."); } + if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeTradesFile -> onFileCreated -> fileContent = " + fileContent); } + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + logger.write(MODULE_NAME, "[ERROR] start -> writeTradesFile -> onFileCreated -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> writeTradesFile -> onFileCreated -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> writeTradesFile -> onFileCreated -> market = " + market.assetA + "_" + market.assetB); + + callBackFunction(err); + return; + + } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeTradesFile -> onFileCreated -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> writeTradesFile -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } +}; From 39ce982afee4df87bca3539e97350cc3e3f1b885 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 14 Aug 2019 12:14:28 +0200 Subject: [PATCH 11/13] Fixing Paula not running --- Commons.js | 5 +++++ Integrations/FileStorage.js | 9 ++++++--- MultiPeriodDaily.js | 13 +++++++++---- Run.js | 9 +++++++-- TradingEngineProcessMainLoop.js | 8 ++++---- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/Commons.js b/Commons.js index 9ada6529f..b49271578 100644 --- a/Commons.js +++ b/Commons.js @@ -369,22 +369,27 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* If any of the needed indicators is missing, then that period is not calculated */ if (candle.begin < initialDate.valueOf()) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Skipping Record before the initialDate."); } controlLoop(); return } if (bollingerBand === undefined) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Skipping Record because Bollinger Band is undefined."); } controlLoop(); return } if (percentageBandwidth === undefined) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Skipping Record because %B is undefined."); } controlLoop(); return } // percentageBandwidth might start after the first few candles. if (bollingerChannel === undefined) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Skipping Record because Bollingeer Channel is undefined."); } controlLoop(); return } if (bollingerSubChannel === undefined) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Skipping Record because Bollingeer Sub Channel is undefined."); } controlLoop(); return } diff --git a/Integrations/FileStorage.js b/Integrations/FileStorage.js index 68014bd70..bc096d472 100644 --- a/Integrations/FileStorage.js +++ b/Integrations/FileStorage.js @@ -6,7 +6,7 @@ const readFileAsync = promisify(fs.readFile) const writeFileAsync = promisify(fs.writeFile) const path = require('path') -exports.newFileStorage = function newFileStorage() { +exports.newFileStorage = function newFileStorage(logger) { const MODULE_NAME = 'FileStorage' const MAX_RETRY = 30 let currentRetryGetTextFile = 0 @@ -37,7 +37,11 @@ exports.newFileStorage = function newFileStorage() { log('[INFO] ' + message) } function log(message) { - console.log("['" + new Date().toISOString() + "', 0,'" + MODULE_NAME + "','" + message + "']") + if (logger) { + logger.write(MODULE_NAME, message); + } else { + console.log("['" + new Date().toISOString() + "', 0,'" + MODULE_NAME + "','" + message + "']") + } } function logError(message) { @@ -46,7 +50,6 @@ exports.newFileStorage = function newFileStorage() { async function getTextFile(container, filePath, callBackFunction) { - try { let host = await getDevTeamHost(container) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 77eba7115..3cfb4dad6 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -21,7 +21,7 @@ let usertBot; const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(logger); let processConfig; @@ -103,6 +103,7 @@ /* The starting date is fixed, we will start from there. */ + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> We have got a user defined startDate. -> startDate = " + processConfig.framework.startDate.fixedDate); } contextVariables.dateBeginOfMarket = new Date(processConfig.framework.startDate.fixedDate); } else { @@ -152,7 +153,7 @@ if (processConfig.framework.endDate.fixedDate !== undefined) { /* The ending date is fixed, we will end there. */ - + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> We have got a user defined endDate. -> endDate = " + processConfig.framework.endDate.fixedDate); } contextVariables.dateEndOfMarket = new Date(processConfig.framework.endDate.fixedDate); } else { @@ -222,6 +223,7 @@ if (bot.hasTheBotJustStarted === true && processConfig.framework.startDate.resumeExecution === false) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Starting from the begining because bot has just started and resume execution was true."); } startFromBegining(); return; } @@ -237,7 +239,7 @@ /* In the case when there is no status report, we assume like the last processed file is the one on the date of Begining of Market. */ - + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Starting from the begining of the market because own status report not found or lastFile was undefined."); } startFromBegining(); return; } @@ -246,7 +248,6 @@ contextVariables.lastFile = new Date(contextVariables.dateBeginOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS); - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> startFromBegining -> thisReport.lastFile === undefined"); } if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> startFromBegining -> contextVariables.lastFile = " + contextVariables.lastFile); } /* @@ -365,6 +366,7 @@ if (period === outputPeriodLabel) { validPeriod = true } } if (validPeriod === false) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Discarding period for not being listed as a valid period. -> outputPeriodLabel = " + outputPeriodLabel); } periodsControlLoop(); return; } @@ -373,6 +375,7 @@ let timePeriodFilter = global.EXECUTION_CONFIG.timePeriodFileStorage if (timePeriodFilter !== undefined) { if (timePeriodFilter.indexOf(outputPeriodLabel) === -1) { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Discarding period for being filtered out. -> outputPeriodLabel = " + outputPeriodLabel); } periodsControlLoop(); return; } @@ -499,6 +502,8 @@ if ((err.result === "Fail Because" && err.message === "File does not exist.") || err.code === 'The specified key does not exist.') { logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> err = " + err.code); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> filePath = " + filePath); + logger.write(MODULE_NAME, "[ERROR] start -> processTimePeriods -> periodsLoopBody -> dependencyLoopBody -> getCurrentFile -> onFileReceived -> fileName = " + fileName); callBackFunction(global.DEFAULT_RETRY_RESPONSE); return; } diff --git a/Run.js b/Run.js index fac89b6b5..1ee41d390 100644 --- a/Run.js +++ b/Run.js @@ -34,7 +34,7 @@ let sequenceList = require('./sequence'); let isRunSequence = false; let sequenceStep = 0; let processedSteps = new Map() -notFirstSequence = false +let notFirstSequence = false if (process.env.RUN_SEQUENCE !== undefined) { isRunSequence = JSON.parse(process.env.RUN_SEQUENCE) @@ -53,7 +53,7 @@ function sequenceExecution(currentStep) { execution.devTeam ? process.env.DEV_TEAM = execution.devTeam : undefined; execution.bot ? process.env.BOT = execution.bot : undefined; execution.mode ? process.env.START_MODE = execution.mode : undefined; - execution.resumeExecution = notFirstSequence + execution.resumeExecution = true; execution.type ? process.env.TYPE = execution.type : undefined; execution.process ? process.env.PROCESS = execution.process : undefined; execution.startYear ? process.env.MIN_YEAR = execution.startYear : undefined; @@ -142,6 +142,11 @@ async function readExecutionConfiguration(execution) { if (execution.type === 'Trading-Engine') { + /* The Trading Engine only resumes its execution after the first sequence was completed. */ + if (notFirstSequence === false) { + execution.resumeExecution = false + } + /* We set the START MODE of the Trading Engine */ if (process.env.KEY === undefined || process.env.SECRET === undefined) { process.env.START_MODE = "backtest" // if we dont have keys, we swtich to backtest mode to avoid exchange errors. diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index f8b03155b..d43569348 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -54,8 +54,8 @@ } USER_BOT_MODULE = {} - USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - //USER_BOT_MODULE.newUserBot = eval(text); // Use this for production + //USER_BOT_MODULE.newUserBot = require(ROOT_DIR + 'User.Bot').newUserBot // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + USER_BOT_MODULE.newUserBot = eval(text); // Use this for production filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo; filePath += "/Commons.js" @@ -70,8 +70,8 @@ return; } COMMONS_MODULE = {} - COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. - //COMMONS_MODULE.newCommons = eval(text); // Use this for production + //COMMONS_MODULE.newCommons = require(ROOT_DIR + 'Commons').newCommons // Use this for a better debugging experience. You need to bring this js module to this folder in order to work. + COMMONS_MODULE.newCommons = eval(text); // Use this for production callBackFunction(global.DEFAULT_OK_RESPONSE); } From 1ab5bc2043c8328867939b36476d558f9d9624a0 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 14 Aug 2019 12:55:19 +0200 Subject: [PATCH 12/13] Moving many logs out of the console into the logs --- Context.js | 2 +- DataSet.js | 2 +- IndicatorBotProcessMainLoop.js | 2 +- MultiPeriodMarket.js | 2 +- SensorBotProcessMainLoop.js | 2 +- StatusReport.js | 2 +- TradingBotProcessMainLoop.js | 2 +- TradingEngineProcessMainLoop.js | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Context.js b/Context.js index 62a6af57f..dc365ec50 100644 --- a/Context.js +++ b/Context.js @@ -66,7 +66,7 @@ /* Storage account to be used here. */ const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(logger); let statusDependencies; diff --git a/DataSet.js b/DataSet.js index ee96308f1..351822890 100644 --- a/DataSet.js +++ b/DataSet.js @@ -15,7 +15,7 @@ exports.newDataSet = function newDataSet(BOT, logger) { /* Storage account to be used here. */ const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(logger); return thisObject; diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js index 9e856c6c1..52707db55 100644 --- a/IndicatorBotProcessMainLoop.js +++ b/IndicatorBotProcessMainLoop.js @@ -11,7 +11,7 @@ const MULTI_PERIOD_MARKET = require(ROOT_DIR + 'MultiPeriodMarket'); const MULTI_PERIOD_DAILY = require(ROOT_DIR + 'MultiPeriodDaily'); const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(parentLogger); const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 38747554f..7f20c8354 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -19,7 +19,7 @@ let usertBot; const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(logger); let processConfig; diff --git a/SensorBotProcessMainLoop.js b/SensorBotProcessMainLoop.js index 6bd875c66..8a6312951 100644 --- a/SensorBotProcessMainLoop.js +++ b/SensorBotProcessMainLoop.js @@ -9,7 +9,7 @@ let COMMONS_MODULE; const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(parentLogger); const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. diff --git a/StatusReport.js b/StatusReport.js index 6023575eb..106dfa3a4 100644 --- a/StatusReport.js +++ b/StatusReport.js @@ -30,7 +30,7 @@ /* Storage account to be used here. */ const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(logger); let month; let year; diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js index f477d4a2b..63ba92fc9 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBotProcessMainLoop.js @@ -10,7 +10,7 @@ const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(parentLogger); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. let nextLoopTimeoutHandle; diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index d43569348..bcfdd1727 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -11,7 +11,7 @@ const MULTI_PERIOD_MARKET = require(ROOT_DIR + 'MultiPeriodMarket'); const MULTI_PERIOD_DAILY = require(ROOT_DIR + 'MultiPeriodDaily'); const FILE_STORAGE = require('./Integrations/FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(); + let fileStorage = FILE_STORAGE.newFileStorage(parentLogger); const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. From 3f6d8f2966799800a2fb7fc653347d588b849fb7 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Wed, 14 Aug 2019 19:13:25 +0200 Subject: [PATCH 13/13] Separeted Logs, timeperiod FIX --- Integrations/FileStorage.js | 9 ++++++++- MultiPeriodDaily.js | 3 ++- MultiPeriodMarket.js | 2 +- Run.js | 18 ++++++++++++++---- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Integrations/FileStorage.js b/Integrations/FileStorage.js index bc096d472..7e780bdf8 100644 --- a/Integrations/FileStorage.js +++ b/Integrations/FileStorage.js @@ -120,7 +120,14 @@ exports.newFileStorage = function newFileStorage(logger) { let host = await getDevTeamHost(container) if (host.url.indexOf('localhost') !== -1) { - let fileLocation = process.env.STORAGE_PATH + '/' + container + '/' + filePath + let fileLocation + + if (filePath.indexOf("/Logs/") > 0) { + fileLocation = process.env.LOG_PATH + '/' + container + '/' + filePath + } else { + fileLocation = process.env.STORAGE_PATH + '/' + container + '/' + filePath + } + logInfo('createTextFile: ' + fileLocation) let directoryPath = fileLocation.substring(0, fileLocation.lastIndexOf('/') + 1); mkDirByPathSync(directoryPath) diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 3cfb4dad6..09f870f6c 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -372,10 +372,11 @@ } } - let timePeriodFilter = global.EXECUTION_CONFIG.timePeriodFileStorage + let timePeriodFilter = global.EXECUTION_CONFIG.timePeriodFilter if (timePeriodFilter !== undefined) { if (timePeriodFilter.indexOf(outputPeriodLabel) === -1) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Discarding period for being filtered out. -> outputPeriodLabel = " + outputPeriodLabel); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimePeriods -> periodsLoopBody -> Discarding period for being filtered out. -> timePeriodFilter = " + timePeriodFilter); } periodsControlLoop(); return; } diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 7f20c8354..619c4a097 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -143,7 +143,7 @@ let dependencyIndex = 0; dataFiles = []; - let timePeriodFilter = global.EXECUTION_CONFIG.timePeriodFileStorage + let timePeriodFilter = global.EXECUTION_CONFIG.timePeriodFilter if (timePeriodFilter !== undefined) { if (timePeriodFilter.indexOf(outputPeriodLabel) === -1) { periodsControlLoop(); diff --git a/Run.js b/Run.js index 1ee41d390..1fa389940 100644 --- a/Run.js +++ b/Run.js @@ -130,7 +130,7 @@ async function readExecutionConfiguration(execution) { try { console.log("[INFO] Run -> readExecutionConfiguration -> Entering function. "); - let timePeriod + let timePeriodFilter let botProcess /* Try to get the begin and end dates from the Definition */ @@ -162,13 +162,13 @@ async function readExecutionConfiguration(execution) { /* Here we only look for one timePeriod, in the future we will be able to process the whole array, but not for now. */ if (definition.simulationParams.timePeriodDailyArray !== undefined) { if (definition.simulationParams.timePeriodDailyArray.length > 0) { - timePeriod = definition.simulationParams.timePeriodDailyArray[0] + timePeriodFilter = definition.simulationParams.timePeriodDailyArray[0] botProcess = "Multi-Period-Daily" } } if (definition.simulationParams.timePeriodMarketArray !== undefined) { if (definition.simulationParams.timePeriodMarketArray.length > 0) { - timePeriod = definition.simulationParams.timePeriodMarketArray[0] + timePeriodFilter = definition.simulationParams.timePeriodMarketArray[0] botProcess = "Multi-Period-Market" } } @@ -307,15 +307,25 @@ async function readExecutionConfiguration(execution) { repo: global.CURRENT_BOT_REPO } - if (timePeriod === undefined) { timePeriod = process.env.TIME_PERIOD } // Only use the .env when nothing comes at Definition.json + let timePeriod + if (timePeriodFilter === undefined) { + timePeriod = process.env.TIME_PERIOD + } else { + timePeriod = timePeriodFilter + } + global.EXECUTION_CONFIG = { cloneToExecute: cloneToExecute, startMode: startMode, timePeriod: getTimePeriod(timePeriod), timePeriodFileStorage: timePeriod, + timePeriodFilter: timePeriodFilter, dataSet: process.env.DATA_SET }; + timePeriodFilter = undefined + timePeriod = undefined + global.CLONE_EXECUTOR = { codeName: 'AACloud', version: '1.1'