From e7e9714f857d1cb952e67c4c5808ca6a185e1efc Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 18 Aug 2019 16:14:41 +0200 Subject: [PATCH] Corrections in Commongs related to muti days trades --- Commons.js | 562 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 464 insertions(+), 98 deletions(-) diff --git a/Commons.js b/Commons.js index 0c2964ef1..dd6a6a7da 100644 --- a/Commons.js +++ b/Commons.js @@ -5,9 +5,9 @@ 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 + 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; @@ -65,6 +65,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> Entering function."); } + let processingDailyFiles = (currentDay !== undefined) + let executionArray = []; let recordsArray = []; let conditionsArray = []; @@ -97,7 +99,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (tradingSystem.parameters !== undefined) { if (tradingSystem.parameters.baseAsset !== undefined) { if (tradingSystem.parameters.baseAsset.formula !== undefined) { - let receivedParameters + let receivedParameters try { receivedParameters = JSON.parse(tradingSystem.parameters.baseAsset.formula.code); @@ -161,18 +163,11 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } } - /* 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 */ @@ -180,17 +175,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { 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; @@ -200,34 +187,11 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { 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. */ + /* In some cases we need to know if we are positioned at the last candle of the calendar day, for that we need these 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 @@ -246,6 +210,45 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { interExecutionMemory. */ + /*Needed for statistics */ + let previousBalanceAssetA = 0; + let previousBalanceAssetB = 0; + + /* Position Management */ + let tradePositionRate = 0; + let tradePositionSize = 0; + + /* Strategy and Phase Management */ + let currentStrategyIndex = -1; + let strategyStage = 'No Stage'; + + let stopLossPhase = 0; + let stopLossStage = 'No Stage'; + + let takeProfitPhase = 0; + let takeProfitStage = 'No Stage'; + + /* 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, + beginRate: 0, + endRate: 0 + } + + let currentTrade = { + begin: 0, + end: 0, + status: 0, + profit: 0, + exitType: 0, + beginRate: 0, + endRate: 0 + } + let balanceAssetA = initialBalanceA; let balanceAssetB = initialBalanceB; @@ -266,6 +269,42 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { let yesterday = {}; + /* Initialization */ + + yesterday.previousBalanceAssetA = previousBalanceAssetA + yesterday.previousBalanceAssetB = previousBalanceAssetB + + yesterday.tradePositionRate = tradePositionRate + yesterday.tradePositionSize = tradePositionSize + + yesterday.currentStrategyIndex = currentStrategyIndex + yesterday.strategyStage = strategyStage + + yesterday.stopLossPhase = stopLossPhase + yesterday.stopLossStage = stopLossStage + + yesterday.takeProfitPhase = takeProfitPhase + yesterday.takeProfitStage = takeProfitStage + + yesterday.currentStrategy = { + begin: 0, + end: 0, + status: 0, + number: 0, + beginRate: 0, + endRate: 0 + } + + yesterday.currentTrade = { + begin: 0, + end: 0, + status: 0, + profit: 0, + exitType: 0, + beginRate: 0, + endRate: 0 + } + yesterday.balanceAssetA = balanceAssetA; yesterday.balanceAssetB = balanceAssetB; @@ -273,10 +312,10 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { yesterday.profit = 0; yesterday.lastTradeROI = 0; - yesterday.Roundtrips = 0; + yesterday.roundtrips = 0; yesterday.fails = 0; yesterday.hits = 0; - yesterday.Periods = 0; + yesterday.periods = 0; yesterday.positionPeriods = 0; yesterday.orderId = 0; @@ -290,6 +329,40 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* Initialize the data structure we will use inter execution. */ + interExecutionMemory.previousBalanceAssetA = previousBalanceAssetA + interExecutionMemory.previousBalanceAssetB = previousBalanceAssetB + + interExecutionMemory.tradePositionRate = tradePositionRate + interExecutionMemory.tradePositionSize = tradePositionSize + + interExecutionMemory.currentStrategyIndex = currentStrategyIndex + interExecutionMemory.strategyStage = strategyStage + + interExecutionMemory.stopLossPhase = stopLossPhase + interExecutionMemory.stopLossStage = stopLossStage + + interExecutionMemory.takeProfitPhase = takeProfitPhase + interExecutionMemory.takeProfitStage = takeProfitStage + + interExecutionMemory.currentStrategy = { + begin: 0, + end: 0, + status: 0, + number: 0, + beginRate: 0, + endRate: 0 + } + + interExecutionMemory.currentTrade = { + begin: 0, + end: 0, + status: 0, + profit: 0, + exitType: 0, + beginRate: 0, + endRate: 0 + } + interExecutionMemory.balanceAssetA = balanceAssetA; interExecutionMemory.balanceAssetB = balanceAssetB; @@ -314,6 +387,40 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* We get the initial values from the day previous to the candles we receive at the current execution */ + previousBalanceAssetA = interExecutionMemory.previousBalanceAssetA + previousBalanceAssetB = interExecutionMemory.previousBalanceAssetB + + tradePositionRate = interExecutionMemory.tradePositionRate + tradePositionSize = interExecutionMemory.tradePositionSize + + currentStrategyIndex = interExecutionMemory.currentStrategyIndex + strategyStage = interExecutionMemory.strategyStage + + stopLossPhase = interExecutionMemory.stopLossPhase + stopLossStage = interExecutionMemory.stopLossStage + + takeProfitPhase = interExecutionMemory.takeProfitPhase + takeProfitStage = interExecutionMemory.takeProfitStage + + currentStrategy = { + begin: interExecutionMemory.currentStrategy.begin, + end: interExecutionMemory.currentStrategy.end, + status: interExecutionMemory.currentStrategy.status, + number: interExecutionMemory.currentStrategy.number, + beginRate: interExecutionMemory.currentStrategy.beginRate, + endRate: interExecutionMemory.currentStrategy.endRate + } + + currentTrade = { + begin: interExecutionMemory.currentTrade.begin, + end: interExecutionMemory.currentTrade.end, + status: interExecutionMemory.currentTrade.status, + profit: interExecutionMemory.currentTrade.profit, + exitType: interExecutionMemory.currentTrade.exitType, + beginRate: interExecutionMemory.currentTrade.beginRate, + endRate: interExecutionMemory.currentTrade.endRate + } + 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; @@ -322,8 +429,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { yesterday.balanceAssetA = balanceAssetA; yesterday.balanceAssetB = balanceAssetB; - } - + } + lastTradeProfitLoss = interExecutionMemory.lastTradeProfitLoss; profit = interExecutionMemory.profit; lastTradeROI = interExecutionMemory.lastTradeROI; @@ -334,19 +441,64 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { periods = interExecutionMemory.periods; positionPeriods = interExecutionMemory.positionPeriods; - orderId = interExecutionMemory.orderId; - messageId = interExecutionMemory.messageId; + orderId = interExecutionMemory.orderId; // to be deprecated + messageId = interExecutionMemory.messageId; // to be deprecated hitRatio = interExecutionMemory.hitRatio; ROI = interExecutionMemory.ROI; anualizedRateOfReturn = interExecutionMemory.anualizedRateOfReturn; + /* For the case that any of these variables are not updated during the main loop, we need to store their value at the yesterday structure, otherwise it would be lost. */ + + yesterday.previousBalanceAssetA = previousBalanceAssetA + yesterday.previousBalanceAssetB = previousBalanceAssetB + + yesterday.tradePositionRate = tradePositionRate + yesterday.tradePositionSize = tradePositionSize + + yesterday.currentStrategyIndex = currentStrategyIndex; + yesterday.strategyStage = strategyStage; + + yesterday.stopLossPhase = stopLossPhase; + yesterday.stopLossStage = stopLossStage; + + yesterday.takeProfitPhase = takeProfitPhase; + yesterday.takeProfitStage = takeProfitStage; + + yesterday.currentStrategy = { + begin: currentStrategy.begin, + end: currentStrategy.end, + status: currentStrategy.status, + number: currentStrategy.number, + beginRate: currentStrategy.beginRate, + endRate: currentStrategy.endRate + } + + yesterday.currentTrade = { + begin: currentTrade.begin, + end: currentTrade.end, + status: currentTrade.status, + profit: currentTrade.profit, + exitType: currentTrade.exitType, + beginRate: currentTrade.beginRate, + endRate: currentTrade.endRate + } + + yesterday.lastTradeProfitLoss = lastTradeProfitLoss; + yesterday.profit = profit; + yesterday.lastTradeROI = lastTradeROI; + + yesterday.roundtrips = roundtrips; + yesterday.fails = fails; + yesterday.hits = hits; + yesterday.periods = periods; + yesterday.positionPeriods = positionPeriods; + 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); } @@ -359,7 +511,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { loop() } - function 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); } @@ -368,6 +521,21 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { let bollingerBand = bollingerBandsMap.get(candle.begin); let bollingerChannel = getElement(bollingerChannelsArray, candle.begin, candle.end); let bollingerSubChannel = getElement(bollingerSubChannelsArray, candle.begin, candle.end); + let positionedAtYesterday = (candle.end < currentDay.valueOf()) + + /* Assistant Info */ + + let ticker + + if (process.env.START_MODE === "live") { + ticker = assistant.getTicker() + } else { + ticker = { + bid: candle.close, + ask: candle.close, + last: candle.close + } + } //let LRC = LRCMap.get(candle.begin); @@ -404,9 +572,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { 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++; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.periods = periods } /* We skip the candle at the head of the market because i has not closed yet. */ @@ -962,6 +1130,16 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentStrategy.beginRate = candle.min; currentStrategy.endRate = candle.min; // In case the strategy does not get exited + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.strategyStage = strategyStage; + yesterday.currentStrategyIndex = currentStrategyIndex; + yesterday.currentStrategy.begin = currentStrategy.begin; + yesterday.currentStrategy.beginRate = currentStrategy.beginRate; + yesterday.currentStrategy.endRate = currentStrategy.endRate; + } + } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Switching to Trigger Stage because conditions at Trigger On Event were met."); } break; } @@ -1018,6 +1196,17 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { strategyStage = 'No Stage'; currentStrategyIndex = -1; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.currentStrategy.number = currentStrategy.number; + yesterday.currentStrategy.end = currentStrategy.end; + yesterday.currentStrategy.endRate = currentStrategy.endRate; + yesterday.currentStrategy.status = currentStrategy.status; + yesterday.strategyStage = strategyStage; + yesterday.currentStrategyIndex = currentStrategyIndex; + } + } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Switching to No Stage because conditions at the Trigger Off Event were met."); } break; } @@ -1065,7 +1254,20 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { stopLossPhase = 1; takeProfitPhase = 1; currentTrade.begin = candle.begin; - currentTrade.beginRate = candle.close; + currentTrade.beginRate = strategy.positionRate; + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.strategyStage = strategyStage; + yesterday.stopLossStage = stopLossStage; + yesterday.takeProfitStage = takeProfitStage; + yesterday.stopLossPhase = stopLossPhase; + yesterday.takeProfitPhase = takeProfitPhase; + yesterday.currentTrade.begin = currentTrade.begin; + yesterday.currentTrade.beginRate = currentTrade.beginRate; + } + } + takePositionNow = true if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Conditions at the Take Position Event were met."); } @@ -1146,6 +1348,14 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { stopLossPhase++; stopLossStage = 'Manage Stage' if (takeProfitPhase > 1) { strategyStage = 'Manage Stage' } + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.stopLossPhase = stopLossPhase; + yesterday.stopLossStage = stopLossStage; + yesterday.strategyStage = strategyStage; + } + } return; } } @@ -1253,6 +1463,14 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { takeProfitPhase++; takeProfitStage = 'Manage Stage' if (stopLossPhase > 1) { strategyStage = 'Manage Stage' } + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.takeProfitPhase = takeProfitPhase; + yesterday.takeProfitStage = takeProfitStage; + yesterday.strategyStage = strategyStage; + } + } return; } } @@ -1292,20 +1510,34 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { /* Keeping Position Counters Up-to-date */ if ( - (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') + (strategyStage === 'Open Stage' || strategyStage === 'Manage Stage') ) { if (takePositionNow === true) { positionPeriods = 0 - yesterday.positionPeriods = 0 + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.positionPeriods = 0 + } + } } positionPeriods++; positionDays = positionPeriods * timePeriod / ONE_DAY_IN_MILISECONDS; - if (currentDay !== undefined) { // This means that we are processing Daily Files - if (candle.end < currentDay.valueOf()) { - yesterday.positionPeriods++; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.positionPeriods = positionPeriods + } + } + } else { + positionPeriods = 0 + positionDays = 0 + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.positionPeriods = 0 } } } @@ -1338,8 +1570,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { balanceAssetA = 0; } - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { + if (processingDailyFiles) { + if (positionedAtYesterday) { yesterday.balanceAssetA = balanceAssetA; yesterday.balanceAssetB = balanceAssetB; } @@ -1359,9 +1591,25 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentStrategy.end = candle.end; currentStrategy.endRate = candle.min; currentStrategy.status = 1; + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.strategyStage = strategyStage; + yesterday.stopLossStage = stopLossStage; + yesterday.takeProfitStage = takeProfitStage; + yesterday.currentTrade.end = currentTrade.end; + yesterday.currentTrade.status = currentTrade.status; + yesterday.currentTrade.exitType = currentTrade.exitType; + yesterday.currentTrade.endRate = currentTrade.endRate; + yesterday.currentStrategy.number = currentStrategy.number; + yesterday.currentStrategy.end = currentStrategy.end; + yesterday.currentStrategy.endRate = currentStrategy.endRate; + yesterday.currentStrategy.status = currentStrategy.status; + } + } } - /* Take Profit condition: Here we verify if the Take Profit was filled or not. */ + /* Take Profit condition: Here we verify if the Take Profit was hit or not. */ if ((baseAsset === 'BTC' && candle.min <= takeProfit) || (baseAsset !== 'BTC' && candle.max >= takeProfit)) { @@ -1379,8 +1627,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { balanceAssetA = 0; } - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { + if (processingDailyFiles) { + if (positionedAtYesterday) { yesterday.balanceAssetA = balanceAssetA; yesterday.balanceAssetB = balanceAssetB; @@ -1392,6 +1640,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { strategyStage = 'Close Stage'; stopLossStage = 'No Stage'; takeProfitStage = 'No Stage'; + currentTrade.end = candle.end; currentTrade.status = 1; currentTrade.exitType = 2; @@ -1401,6 +1650,24 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentStrategy.end = candle.end; currentStrategy.endRate = candle.min; currentStrategy.status = 1; + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.strategyStage = strategyStage; + yesterday.stopLossStage = stopLossStage; + yesterday.takeProfitStage = takeProfitStage; + + yesterday.currentTrade.end = currentTrade.end; + yesterday.currentTrade.status = currentTrade.status; + yesterday.currentTrade.exitType = currentTrade.exitType; + yesterday.currentTrade.endRate = currentTrade.endRate; + + yesterday.currentStrategy.number = currentStrategy.number; + yesterday.currentStrategy.end = currentStrategy.end; + yesterday.currentStrategy.endRate = currentStrategy.endRate; + yesterday.currentStrategy.status = currentStrategy.status; + } + } } } @@ -1417,6 +1684,13 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { tradePositionSize = strategy.positionSize; tradePositionRate = strategy.positionRate; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.tradePositionSize = tradePositionSize; + yesterday.tradePositionRate = tradePositionRate; + } + } + /* Check that we are in LIVE MODE */ if (process.env.START_MODE === "live") { /* We see if we need to put the actual order at the exchange. */ @@ -1501,7 +1775,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (interExecutionMemory.executionContext !== undefined) { if (interExecutionMemory.executionContext.periods !== undefined) { if (periods <= interExecutionMemory.executionContext.periods) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because it was already placed at a previous execution." ); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> putOpeningOrder -> Not placing the trade at the exchange because it was already placed at a previous execution."); } takePositionAtSimulation() return; } @@ -1509,7 +1783,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } /* 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 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 -> loop -> 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."); } @@ -1527,7 +1801,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { if (baseAsset === 'BTC') { positionDirection = "sell" - openPositionRate = tradePositionRate + openPositionRate = tradePositionRate amountA = tradePositionSize * openPositionRate amountB = tradePositionSize @@ -1536,7 +1810,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { openPositionRate = tradePositionRate - amountA = tradePositionSize + amountA = tradePositionSize amountB = tradePositionSize / openPositionRate } @@ -1602,6 +1876,13 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { previousBalanceAssetA = balanceAssetA; previousBalanceAssetB = balanceAssetB; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.previousBalanceAssetA = previousBalanceAssetA; + yesterday.previousBalanceAssetB = previousBalanceAssetB; + } + } + lastTradeProfitLoss = 0; lastTradeROI = 0; @@ -1613,10 +1894,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { balanceAssetB = balanceAssetB - tradePositionSize; } - positionInstant = candle.end; - - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { + if (processingDailyFiles) { + if (positionedAtYesterday) { yesterday.balanceAssetA = balanceAssetA; yesterday.balanceAssetB = balanceAssetB; @@ -1677,7 +1956,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } closePositionAtSimulation() - return + return function putClosingOrder() { @@ -1781,9 +2060,9 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { roundtrips++; - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { - yesterday.Roundtrips++; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.roundtrips = roundtrips } } @@ -1799,8 +2078,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { profit = balanceAssetB - initialBalanceB; } - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { + if (processingDailyFiles) { + if (positionedAtYesterday) { yesterday.lastTradeProfitLoss = lastTradeProfitLoss; yesterday.profit = profit; yesterday.lastTradeROI = lastTradeROI; @@ -1810,21 +2089,28 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { currentTrade.lastTradeROI = lastTradeROI; currentTrade.stopRate = stopLoss; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.currentTrade.lastTradeROI = currentTrade.lastTradeROI; + yesterday.currentTrade.stopRate = currentTrade.stopRate; + } + } + if (lastTradeProfitLoss > 0) { hits++; - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { - yesterday.hits++; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.hits = hits } } } else { fails++; - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { - yesterday.fails++; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.fails = fails } } } @@ -1839,8 +2125,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { anualizedRateOfReturn = ROI / days * 365; } - if (currentDay !== undefined) { - if (positionInstant < currentDay.valueOf()) { + if (processingDailyFiles) { + if (positionedAtYesterday) { yesterday.ROI = ROI; yesterday.hitRatio = hitRatio; yesterday.anualizedRateOfReturn = anualizedRateOfReturn; @@ -1849,18 +2135,37 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { addRecord(); - currentStrategyIndex = -1; stopLoss = 0; + takeProfit = 0; + tradePositionRate = 0; tradePositionSize = 0; - positionInstant = undefined; - takeProfit = 0; + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.tradePositionSize = tradePositionSize; + yesterday.tradePositionRate = tradePositionRate; + } + } + + currentStrategyIndex = -1; strategyStage = 'No Stage'; stopLossStage = 'No Stage'; takeProfitStage = 'No Stage'; stopLossPhase = 0; takeProfitPhase = 0; + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.currentStrategyIndex = currentStrategyIndex; + yesterday.strategyStage = strategyStage; + yesterday.stopLossStage = stopLossStage; + yesterday.takeProfitStage = takeProfitStage; + yesterday.stopLossPhase = stopLossPhase; + yesterday.takeProfitPhase = takeProfitPhase; + } + } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> closePositionAtSimulation -> Exiting Loop Body after closing position at simulation."); } controlLoop(); return @@ -2080,6 +2385,19 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { beginRate: 0, endRate: 0 } + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.currentStrategy = { + begin: 0, + end: 0, + status: 0, + number: 0, + beginRate: 0, + endRate: 0 + } + } + } } /* Prepare the information for the Trades File */ @@ -2102,6 +2420,20 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { beginRate: 0, endRate: 0 } + + if (processingDailyFiles) { + if (positionedAtYesterday) { + yesterday.currentTrade = { + begin: 0, + end: 0, + status: 0, + lastTradeROI: 0, + exitType: 0, + beginRate: 0, + endRate: 0 + } + } + } } } } @@ -2124,21 +2456,55 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { To do that, the condition to be met is that this execution must include all candles of the currentDay. */ - if (currentDay !== undefined) { + if (processingDailyFiles) { if (lastCandle.end === lastInstantOfTheDay) { + interExecutionMemory.previousBalanceAssetA = yesterday.previousBalanceAssetA + interExecutionMemory.previousBalanceAssetB = yesterday.previousBalanceAssetB + + interExecutionMemory.tradePositionRate = yesterday.tradePositionRate + interExecutionMemory.tradePositionSize = yesterday.tradePositionSize + + interExecutionMemory.currentStrategyIndex = yesterday.currentStrategyIndex + interExecutionMemory.strategyStage = yesterday.strategyStage + + interExecutionMemory.stopLossPhase = yesterday.stopLossPhase + interExecutionMemory.stopLossStage = yesterday.stopLossStage + + interExecutionMemory.takeProfitPhase = yesterday.takeProfitPhase + interExecutionMemory.takeProfitStage = yesterday.takeProfitStage + + interExecutionMemory.currentStrategy = { + begin: yesterday.currentStrategy.begin, + end: yesterday.currentStrategy.end, + status: yesterday.currentStrategy.status, + number: yesterday.currentStrategy.number, + beginRate: yesterday.currentStrategy.beginRate, + endRate: yesterday.currentStrategy.endRate + } + + interExecutionMemory.currentTrade = { + begin: yesterday.currentTrade.begin, + end: yesterday.currentTrade.end, + status: yesterday.currentTrade.status, + profit: yesterday.currentTrade.profit, + exitType: yesterday.currentTrade.exitType, + beginRate: yesterday.currentTrade.beginRate, + endRate: yesterday.currentTrade.endRate + } + 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.positionPeriods = interExecutionMemory.positionPeriods + yesterday.positionPeriods; + interExecutionMemory.roundtrips = yesterday.roundtrips; + interExecutionMemory.fails = yesterday.fails; + interExecutionMemory.hits = yesterday.hits; + interExecutionMemory.periods = yesterday.periods; + interExecutionMemory.positionPeriods = yesterday.positionPeriods; interExecutionMemory.messageId = interExecutionMemory.messageId + yesterday.messageId; interExecutionMemory.orderId = interExecutionMemory.orderId + yesterday.orderId; @@ -2168,7 +2534,7 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { } } - return + return } } catch (err) {