From d36c6e7b7f7d1caeaa0de8f704a824f409fac7e5 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Fri, 7 Aug 2020 13:11:52 +0200 Subject: [PATCH] Episode Module Implemented --- LowFrequencyTrading/Snapshots.js | 2 +- LowFrequencyTrading/TradingEngine.js | 6 - LowFrequencyTrading/TradingEpisode.js | 203 +++++++++++++++++++++++ LowFrequencyTrading/TradingPosition.js | 6 +- LowFrequencyTrading/TradingSimulation.js | 58 +++++-- LowFrequencyTrading/TradingStages.js | 135 ++------------- LowFrequencyTrading/TradingStrategy.js | 10 +- 7 files changed, 269 insertions(+), 151 deletions(-) create mode 100644 LowFrequencyTrading/TradingEpisode.js diff --git a/LowFrequencyTrading/Snapshots.js b/LowFrequencyTrading/Snapshots.js index 11b3e6eae..1f4559fb3 100644 --- a/LowFrequencyTrading/Snapshots.js +++ b/LowFrequencyTrading/Snapshots.js @@ -253,7 +253,7 @@ exports.newSnapshots = function newSnapshots(bot, logger) { let closeHeaders = ['Trade Number', 'Open Datetime', 'Close Datetime', 'Strategy Name', 'Trigger On Situation', 'Take Position Situation', 'Result In Base Asset', 'Result In Quoted Asset', 'ROI in Base Asset', 'ROI in Quoted Asset', 'Exit Type'] closeValues = [ - tradingEngine.current.episode.episodeCounters.positions.value, // Position Number + tradingEngine.current.episode.episodeCounters.positions.value, // Position Number (new Date(openDatetime)).toISOString(), // Open Datetime (new Date(closeDatetime)).toISOString(), // Open Datetime tradingEngine.current.strategy.strategyName.value, // Strategy Name diff --git a/LowFrequencyTrading/TradingEngine.js b/LowFrequencyTrading/TradingEngine.js index 502be24ad..981f71183 100644 --- a/LowFrequencyTrading/TradingEngine.js +++ b/LowFrequencyTrading/TradingEngine.js @@ -8,7 +8,6 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) { getNodeById: getNodeById, cloneValues: cloneValues, setCurrentCandle: setCurrentCandle, - updateEpisodeCountersAndStatistics: updateEpisodeCountersAndStatistics, updateDistanceToEventsCounters: updateDistanceToEventsCounters, initialize: initialize, finalize: finalize @@ -141,11 +140,6 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) { } } - function updateEpisodeCountersAndStatistics() { - tradingEngine.current.episode.episodeCounters.periods.value++ - tradingEngine.current.episode.episodeStatistics.days.value = tradingEngine.current.episode.episodeCounters.periods.value * sessionParameters.timeFrame.config.value / global.ONE_DAY_IN_MILISECONDS - } - function updateDistanceToEventsCounters() { /* Keeping Distance Counters Up-to-date while avoinding counting before the first event happens. */ if ( diff --git a/LowFrequencyTrading/TradingEpisode.js b/LowFrequencyTrading/TradingEpisode.js new file mode 100644 index 000000000..194532833 --- /dev/null +++ b/LowFrequencyTrading/TradingEpisode.js @@ -0,0 +1,203 @@ +exports.newTradingEpisode = function newTradingEpisode(bot, logger) { + /* + This module packages all functions related to Episodes. + */ + const MODULE_NAME = 'Trading Episode' + let thisObject = { + openEpisode: openEpisode, + closingEpisode: closingEpisode, + closeEpisode: closeEpisode, + updateEnds: updateEnds, + resetTradingEngineDataStructure: resetTradingEngineDataStructure, + updateCounters: updateCounters, + updateStatistics: updateStatistics, + calculateResults: calculateResults, + calculateStatistics: calculateStatistics, + initialize: initialize, + finalize: finalize + } + + let tradingEngine + let tradingSystem + let sessionParameters + + return thisObject + + function initialize() { + tradingSystem = bot.simulationState.tradingSystem + tradingEngine = bot.simulationState.tradingEngine + sessionParameters = bot.SESSION.parameters + } + + function finalize() { + tradingEngine = undefined + tradingSystem = undefined + sessionParameters = undefined + } + + function openEpisode() { + + /* Recording the opening at the Trading Engine Data Structure */ + tradingEngine.current.episode.status.value = 'Open' + tradingEngine.current.episode.serialNumber.value = 1 + tradingEngine.current.episode.identifier.value = global.UNIQUE_ID() + tradingEngine.current.episode.begin.value = tradingEngine.current.candle.begin.value + tradingEngine.current.episode.beginRate.value = tradingEngine.current.candle.close.value + } + + function closingEpisode(exitType) { + tradingEngine.current.episode.status.value = 'Closing' + tradingEngine.current.episode.exitType.value = exitType + } + + function closeEpisode() { + tradingEngine.current.episode.status.value = 'Closed' + tradingEngine.current.episode.end.value = tradingEngine.current.candle.end.value + tradingEngine.current.episode.endRate.value = tradingEngine.current.candle.close.value + } + + function resetEpisode() { + tradingEngine.current.episode.initialize(tradingEngine.current.episode) + } + + function updateEnds() { + if (tradingEngine.current.episode.status.value === 'Open') { + tradingEngine.current.episode.end.value = tradingEngine.current.candle.end.value + tradingEngine.current.episode.endRate.value = tradingEngine.current.candle.close.value + } + } + + function resetTradingEngineDataStructure() { + if (tradingEngine.current.episode.status.value === 'Closed') { + resetEpisode() + } + } + + function updateCounters() { + if (tradingEngine.current.episode.status.value === 'Open') { + tradingEngine.current.episode.episodeCounters.periods.value++ + } + } + + function updateStatistics() { + + /* Daus Calculation */ + tradingEngine.current.episode.episodeStatistics.days.value = + tradingEngine.current.episode.episodeCounters.periods.value * + sessionParameters.timeFrame.config.value / + global.ONE_DAY_IN_MILISECONDS + } + + function calculateStatistics() { + + /* Updating Profit Loss */ + tradingEngine.current.episode.episodeStatistics.profitLoss.value = + tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.candle.close.value + + tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value + + tradingEngine.current.episode.episodeStatistics.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeStatistics.profitLoss.value, 10) + + /* Updating ROI */ + tradingEngine.current.episode.episodeStatistics.ROI.value = + ( + sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.candle.close.value + + tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.candle.close.value + + sessionParameters.sessionQuotedAsset.config.initialBalance + + tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value + ) / ( + sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.candle.close.value + + sessionParameters.sessionQuotedAsset.config.initialBalance + ) - 1 + + tradingEngine.current.episode.episodeStatistics.ROI.value = global.PRECISE(tradingEngine.current.episode.episodeStatistics.ROI.value, 10) + + /* Updating Anualized Rate Of Return */ + tradingEngine.current.episode.episodeStatistics.anualizedRateOfReturn.value = + tradingEngine.current.episode.episodeStatistics.ROI.value / + tradingEngine.current.episode.episodeStatistics.days.value * 365 + + tradingEngine.current.episode.episodeStatistics.anualizedRateOfReturn.value = global.PRECISE(tradingEngine.current.episode.episodeStatistics.anualizedRateOfReturn.value, 10) + + /* Updating Hit or Fail */ + if (tradingEngine.current.episode.episodeStatistics.profitLoss.value > 0) { + tradingEngine.current.episode.episodeStatistics.hitFail.value = 'Hit' + } else { + tradingEngine.current.episode.episodeStatistics.hitFail.value = 'Fail' + } + } + + function calculateResults() { + + /* Updating Hits & Fails */ + if (tradingEngine.current.position.positionBaseAsset.profitLoss.value > 0) { + tradingEngine.current.episode.episodeBaseAsset.hits.value++ + } else { + tradingEngine.current.episode.episodeBaseAsset.fails.value++ + } + if (tradingEngine.current.position.positionQuotedAsset.profitLoss.value > 0) { + tradingEngine.current.episode.episodeQuotedAsset.hits.value++ + } else { + tradingEngine.current.episode.episodeQuotedAsset.fails.value++ + } + + /* Updating Profit Loss */ + tradingEngine.current.episode.episodeBaseAsset.profitLoss.value = + tradingEngine.current.balance.baseAsset.value - + sessionParameters.sessionBaseAsset.config.initialBalance + + tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value = + tradingEngine.current.balance.quotedAsset.value - + sessionParameters.sessionQuotedAsset.config.initialBalance + + tradingEngine.current.episode.episodeBaseAsset.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.profitLoss.value, 10) + tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value, 10) + + /* Updating ROI */ + tradingEngine.current.episode.episodeBaseAsset.ROI.value = + (sessionParameters.sessionBaseAsset.config.initialBalance + tradingEngine.current.episode.episodeBaseAsset.profitLoss.value) / + sessionParameters.sessionBaseAsset.config.initialBalance - 1 + + tradingEngine.current.episode.episodeQuotedAsset.ROI.value = + (sessionParameters.sessionQuotedAsset.config.initialBalance + tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value) / + sessionParameters.sessionQuotedAsset.config.initialBalance - 1 + + tradingEngine.current.episode.episodeBaseAsset.ROI.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.ROI.value, 10) + tradingEngine.current.episode.episodeQuotedAsset.ROI.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.ROI.value, 10) + + /* Updating Hit Ratio */ + tradingEngine.current.episode.episodeBaseAsset.hitRatio.value = + tradingEngine.current.episode.episodeBaseAsset.hits.value / + tradingEngine.current.episode.episodeCounters.positions.value + + tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value = + tradingEngine.current.episode.episodeQuotedAsset.hits.value / + tradingEngine.current.episode.episodeCounters.positions.value + + tradingEngine.current.episode.episodeBaseAsset.hitRatio.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.hitRatio.value, 10) + tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value, 10) + + /* Updating Anualized Rate Of Return */ + tradingEngine.current.episode.episodeBaseAsset.anualizedRateOfReturn.value = + tradingEngine.current.episode.episodeBaseAsset.ROI.value / + tradingEngine.current.episode.episodeStatistics.days.value * 365 + + tradingEngine.current.episode.episodeQuotedAsset.anualizedRateOfReturn.value = + tradingEngine.current.episode.episodeQuotedAsset.ROI.value / + tradingEngine.current.episode.episodeStatistics.days.value * 365 + + tradingEngine.current.episode.episodeBaseAsset.anualizedRateOfReturn.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.anualizedRateOfReturn.value, 10) + tradingEngine.current.episode.episodeQuotedAsset.anualizedRateOfReturn.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.anualizedRateOfReturn.value, 10) + + /* Updating Hit or Fail */ + if (tradingEngine.current.episode.episodeBaseAsset.profitLoss.value > 0) { + tradingEngine.current.episode.episodeBaseAsset.hitFail.value = 'Hit' + } else { + tradingEngine.current.episode.episodeBaseAsset.hitFail.value = 'Fail' + } + if (tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value > 0) { + tradingEngine.current.episode.episodeQuotedAsset.hitFail.value = 'Hit' + } else { + tradingEngine.current.episode.episodeQuotedAsset.hitFail.value = 'Fail' + } + } +} \ No newline at end of file diff --git a/LowFrequencyTrading/TradingPosition.js b/LowFrequencyTrading/TradingPosition.js index b725758b9..885292b4e 100644 --- a/LowFrequencyTrading/TradingPosition.js +++ b/LowFrequencyTrading/TradingPosition.js @@ -13,7 +13,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng updateTakeProfit: updateTakeProfit, initialTargets: initialTargets, updateEnds: updateEnds, - updateStatus: updateStatus, + resetTradingEngineDataStructure: resetTradingEngineDataStructure, updateCounters: updateCounters, resetPosition: resetPosition, initialize: initialize, @@ -46,7 +46,6 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng tradingEngine.current.position.identifier.value = global.UNIQUE_ID() tradingEngine.current.position.begin.value = tradingEngine.current.candle.begin.value tradingEngine.current.position.beginRate.value = tradingEngine.current.candle.close.value - tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value tradingEngine.current.position.situationName.value = situationName /* Initializing Stop and Take Profit Stage / Phase */ @@ -225,10 +224,11 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng function updateEnds() { if (tradingEngine.current.position.status.value === 'Open') { tradingEngine.current.position.end.value = tradingEngine.current.candle.end.value + tradingEngine.current.position.endRate.value = tradingEngine.current.candle.close.value } } - function updateStatus() { + function resetTradingEngineDataStructure() { if (tradingEngine.current.position.status.value === 'Closed') { resetPosition() } diff --git a/LowFrequencyTrading/TradingSimulation.js b/LowFrequencyTrading/TradingSimulation.js index cc07cb796..509b3ca87 100644 --- a/LowFrequencyTrading/TradingSimulation.js +++ b/LowFrequencyTrading/TradingSimulation.js @@ -46,6 +46,10 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT let tradingSystemModule = TRADING_SYSTEM_MODULE.newTradingSystem(bot, logger, tradingEngineModule) tradingSystemModule.initialize() + const TRADING_EPISODE_MODULE = require('./TradingEpisode.js') + let tradingEpisodeModule = TRADING_EPISODE_MODULE.newTradingEpisode(bot, logger) + tradingEpisodeModule.initialize() + /* Setting up the candles array: The whole simulation is based on the array of candles at the time-frame defined at the session parameters. */ let propertyName = 'at' + sessionParameters.timeFrame.config.label.replace('-', '') let candles = chart[propertyName].candles @@ -53,6 +57,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT /* Variables needed for heartbeat functionality */ let heartBeatDate let previousHeartBeatDate + let firstLoopExecution = true initializeLoop() @@ -106,13 +111,18 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT tradingEngineModule.setCurrentCandle(candle) // We move the current candle we are standing at, to the trading engine data structure to make it available to anyone, including conditions and formulas. - if (checkIfWeAreAtTheHeadOfTheMarket() === false) { - afterLoop() + if (firstLoopExecution === true) { + tradingEpisodeModule.openEpisode() + firstLoopExecution = false + } + + if (checkLastCandle() === false) { + closeEpisode('Last Candle Reached') return } if (checkMinimunAndMaximunBalance() === false) { - afterLoop() + closeEpisode('Min or Max Balance Reached') return } @@ -130,15 +140,15 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT /* Do the stuff needed previous to the run */ tradingSystemModule.mantain() - tradingEngineModule.updateEpisodeCountersAndStatistics() + /* Episode Counters and Statistics */ + tradingEpisodeModule.updateCounters() + tradingEpisodeModule.updateStatistics() + tradingEngineModule.updateDistanceToEventsCounters() /* Run one cycle of the Trading System*/ await tradingSystemModule.run() - /* Add new records to the process output */ - tradingRecordsModule.appendRecords() - controlLoop() } @@ -147,33 +157,51 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT if (bot.STOP_SESSION === true) { if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this session.') } console.log('[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this session.') - afterLoop() + closeEpisode('Session Stopped') return } if (global.STOP_TASK_GRACEFULLY === true) { if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this task.') } console.log('[INFO] runSimulation -> controlLoop -> We are going to stop here bacause we were requested to stop processing this task.') - afterLoop() + closeEpisode('Task Stopped') return } - tradingEngine.current.candle.index.value++ - if (tradingEngine.current.candle.index.value < candles.length) { + if (tradingEngine.current.candle.index.value + 1 < candles.length) { + + /* Add new records to the process output */ + tradingRecordsModule.appendRecords() + + tradingEngine.current.candle.index.value++ + setImmediate(loop) // This will execute the next loop in the next iteration of the NodeJs event loop allowing for other callbacks to be executed. } else { - afterLoop() + closeEpisode('All Candles Processed') } } + function closeEpisode(exitType) { + tradingEpisodeModule.closingEpisode(exitType) + tradingEpisodeModule.closeEpisode() + + /* Add new records to the process output */ + tradingRecordsModule.appendRecords() + + afterLoop() + } + function afterLoop() { + tradingEngineModule.finalize() tradingSystemModule.finalize() tradingRecordsModule.finalize() + tradingEpisodeModule.finalize() tradingEngineModule = undefined tradingSystemModule = undefined tradingRecordsModule = undefined + tradingEpisodeModule = undefined callback() } @@ -301,7 +329,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT } } - function checkIfWeAreAtTheHeadOfTheMarket() { + function checkLastCandle() { /* We skip the candle at the head of the market because it has not closed yet. The procedure to determine if we are at the head of the market is different when we are processing Market Files than when we are processing Daily Files. TODO Check that the procedure is good for Beta 6 @@ -310,7 +338,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT let candlesPerDay = global.ONE_DAY_IN_MILISECONDS / sessionParameters.timeFrame.config.value if (tradingEngine.current.candle.index.value === candles.length - 1) { if ((candles.length < candlesPerDay) || (candles.length > candlesPerDay && candles.length < candlesPerDay * 2)) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkIfWeAreAtTheHeadOfTheMarket -> Skipping Candle because it is the last one and has not been closed yet.') } + if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkLastCandle -> Skipping Candle because it is the last one and has not been closed yet.') } return false /* 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. @@ -320,7 +348,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT } } else { // We are processing Market Files if (tradingEngine.current.candle.index.value === candles.length - 1) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkIfWeAreAtTheHeadOfTheMarket -> Skipping Candle because it is the last one and has not been closed yet.') } + if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkLastCandle -> Skipping Candle because it is the last one and has not been closed yet.') } return false } } diff --git a/LowFrequencyTrading/TradingStages.js b/LowFrequencyTrading/TradingStages.js index 2e1550282..8e7507047 100644 --- a/LowFrequencyTrading/TradingStages.js +++ b/LowFrequencyTrading/TradingStages.js @@ -11,7 +11,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM runManageStage: runManageStage, runCloseStage: runCloseStage, updateEnds: updateEnds, - updateStatus: updateStatus, + resetTradingEngineDataStructure: resetTradingEngineDataStructure, updateCounters: updateCounters, updateStatistics: updateStatistics, resetStage: resetStage, @@ -34,6 +34,8 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM const SNAPSHOTS_MODULE = require('./Snapshots.js') let snapshotsModule = SNAPSHOTS_MODULE.newSnapshots(bot, logger) + const TRADING_EPISODE_MODULE = require('./TradingEpisode.js') + let tradingEpisodeModule = TRADING_EPISODE_MODULE.newTradingEpisode(bot, logger) let tradingEngine let tradingSystem @@ -51,6 +53,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM announcementsModule.initialize() snapshotsModule.initialize() tradingExecutionModule.initialize() + tradingEpisodeModule.initialize() } function finalize() { @@ -72,6 +75,9 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM tradingExecutionModule.finalize() tradingExecutionModule = undefined + + tradingEpisodeModule.finalize() + tradingEpisodeModule = undefined } function updateChart(pChart) { @@ -85,19 +91,19 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM mantainOrders() function mantainStrategies() { - tradingStrategyModule.updateStatus() + tradingStrategyModule.resetTradingEngineDataStructure() tradingStrategyModule.updateCounters() tradingStrategyModule.updateEnds() } function mantainStages() { - updateStatus() + resetTradingEngineDataStructure() updateCounters() updateEnds() } function mantainPositions() { - tradingPositionModule.updateStatus() + tradingPositionModule.resetTradingEngineDataStructure() tradingPositionModule.updateCounters() tradingPositionModule.updateEnds() } @@ -202,9 +208,6 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM tradingStrategyModule.openStrategy(j, situation.name, strategy.name) - /* Updating Episode Counters */ - tradingEngine.current.episode.episodeCounters.strategies.value++ - /* Initialize this */ tradingEngine.current.distanceToEvent.triggerOn.value = 1 @@ -1013,8 +1016,8 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM /* Close the Position */ tradingPositionModule.closePosition() - updatingEpisodeAssets() - updatingEpisodeStatistics() + tradingEpisodeModule.calculateResults() + tradingEpisodeModule.calculateStatistics() /* Close the Strategy */ tradingStrategyModule.closeStrategy('Position Closed') @@ -1023,118 +1026,6 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM tradingEngine.current.distanceToEvent.closePosition.value = 1 tradingEngine.current.distanceToEvent.triggerOff.value = 1 - function updatingEpisodeAssets() { - - /* Updating Hits & Fails */ - if (tradingEngine.current.position.positionBaseAsset.profitLoss.value > 0) { - tradingEngine.current.episode.episodeBaseAsset.hits.value++ - } else { - tradingEngine.current.episode.episodeBaseAsset.fails.value++ - } - if (tradingEngine.current.position.positionQuotedAsset.profitLoss.value > 0) { - tradingEngine.current.episode.episodeQuotedAsset.hits.value++ - } else { - tradingEngine.current.episode.episodeQuotedAsset.fails.value++ - } - - /* Updating Profit Loss */ - tradingEngine.current.episode.episodeBaseAsset.profitLoss.value = - tradingEngine.current.balance.baseAsset.value - - sessionParameters.sessionBaseAsset.config.initialBalance - - tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value = - tradingEngine.current.balance.quotedAsset.value - - sessionParameters.sessionQuotedAsset.config.initialBalance - - tradingEngine.current.episode.episodeBaseAsset.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.profitLoss.value, 10) - tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value, 10) - - /* Updating ROI */ - tradingEngine.current.episode.episodeBaseAsset.ROI.value = - (sessionParameters.sessionBaseAsset.config.initialBalance + tradingEngine.current.episode.episodeBaseAsset.profitLoss.value) / - sessionParameters.sessionBaseAsset.config.initialBalance - 1 - - tradingEngine.current.episode.episodeQuotedAsset.ROI.value = - (sessionParameters.sessionQuotedAsset.config.initialBalance + tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value) / - sessionParameters.sessionQuotedAsset.config.initialBalance - 1 - - tradingEngine.current.episode.episodeBaseAsset.ROI.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.ROI.value, 10) - tradingEngine.current.episode.episodeQuotedAsset.ROI.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.ROI.value, 10) - - /* Updating Hit Ratio */ - tradingEngine.current.episode.episodeBaseAsset.hitRatio.value = - tradingEngine.current.episode.episodeBaseAsset.hits.value / - tradingEngine.current.episode.episodeCounters.positions.value - - tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value = - tradingEngine.current.episode.episodeQuotedAsset.hits.value / - tradingEngine.current.episode.episodeCounters.positions.value - - tradingEngine.current.episode.episodeBaseAsset.hitRatio.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.hitRatio.value, 10) - tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.hitRatio.value, 10) - - /* Updating Anualized Rate Of Return */ - tradingEngine.current.episode.episodeBaseAsset.anualizedRateOfReturn.value = - tradingEngine.current.episode.episodeBaseAsset.ROI.value / - tradingEngine.current.episode.episodeStatistics.days.value * 365 - - tradingEngine.current.episode.episodeQuotedAsset.anualizedRateOfReturn.value = - tradingEngine.current.episode.episodeQuotedAsset.ROI.value / - tradingEngine.current.episode.episodeStatistics.days.value * 365 - - tradingEngine.current.episode.episodeBaseAsset.anualizedRateOfReturn.value = global.PRECISE(tradingEngine.current.episode.episodeBaseAsset.anualizedRateOfReturn.value, 10) - tradingEngine.current.episode.episodeQuotedAsset.anualizedRateOfReturn.value = global.PRECISE(tradingEngine.current.episode.episodeQuotedAsset.anualizedRateOfReturn.value, 10) - - /* Updating Hit or Fail */ - if (tradingEngine.current.episode.episodeBaseAsset.profitLoss.value > 0) { - tradingEngine.current.episode.episodeBaseAsset.hitFail.value = 'Hit' - } else { - tradingEngine.current.episode.episodeBaseAsset.hitFail.value = 'Fail' - } - if (tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value > 0) { - tradingEngine.current.episode.episodeQuotedAsset.hitFail.value = 'Hit' - } else { - tradingEngine.current.episode.episodeQuotedAsset.hitFail.value = 'Fail' - } - } - - function updatingEpisodeStatistics() { - - /* Updating Profit Loss */ - tradingEngine.current.episode.episodeStatistics.profitLoss.value = - tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.candle.close.value + - tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value - - tradingEngine.current.episode.episodeStatistics.profitLoss.value = global.PRECISE(tradingEngine.current.episode.episodeStatistics.profitLoss.value, 10) - - /* Updating ROI */ - tradingEngine.current.episode.episodeStatistics.ROI.value = - ( - sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.candle.close.value + - tradingEngine.current.episode.episodeBaseAsset.profitLoss.value * tradingEngine.current.candle.close.value + - sessionParameters.sessionQuotedAsset.config.initialBalance + - tradingEngine.current.episode.episodeQuotedAsset.profitLoss.value - ) / ( - sessionParameters.sessionBaseAsset.config.initialBalance * tradingEngine.current.candle.close.value + - sessionParameters.sessionQuotedAsset.config.initialBalance - ) - 1 - - tradingEngine.current.episode.episodeStatistics.ROI.value = global.PRECISE(tradingEngine.current.episode.episodeStatistics.ROI.value, 10) - - /* Updating Anualized Rate Of Return */ - tradingEngine.current.episode.episodeStatistics.anualizedRateOfReturn.value = - tradingEngine.current.episode.episodeStatistics.ROI.value / - tradingEngine.current.episode.episodeStatistics.days.value * 365 - - tradingEngine.current.episode.episodeStatistics.anualizedRateOfReturn.value = global.PRECISE(tradingEngine.current.episode.episodeStatistics.anualizedRateOfReturn.value, 10) - - /* Updating Hit or Fail */ - if (tradingEngine.current.episode.episodeStatistics.profitLoss.value > 0) { - tradingEngine.current.episode.episodeStatistics.hitFail.value = 'Hit' - } else { - tradingEngine.current.episode.episodeStatistics.hitFail.value = 'Fail' - } - } } } @@ -1229,7 +1120,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM } } - function updateStatus() { + function resetTradingEngineDataStructure() { if (tradingEngine.current.strategyTriggerStage.status.value === 'Closed') { resetStage(tradingEngine.current.strategyTriggerStage.status) } diff --git a/LowFrequencyTrading/TradingStrategy.js b/LowFrequencyTrading/TradingStrategy.js index 5006e3eb6..3572dee68 100644 --- a/LowFrequencyTrading/TradingStrategy.js +++ b/LowFrequencyTrading/TradingStrategy.js @@ -7,7 +7,7 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng openStrategy: openStrategy, closeStrategy: closeStrategy, updateEnds: updateEnds, - updateStatus: updateStatus, + resetTradingEngineDataStructure: resetTradingEngineDataStructure, updateCounters: updateCounters, resetStrategy: resetStrategy, initialize: initialize, @@ -33,11 +33,13 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng tradingEngine.current.strategy.begin.value = tradingEngine.current.candle.begin.value tradingEngine.current.strategy.end.value = tradingEngine.current.candle.end.value tradingEngine.current.strategy.beginRate.value = tradingEngine.current.candle.min.value - tradingEngine.current.strategy.endRate.value = tradingEngine.current.candle.min.value tradingEngine.current.strategy.index.value = index tradingEngine.current.strategy.situationName.value = situationName tradingEngine.current.strategy.strategyName.value = strategyName + + /* Updating Episode Counters */ + tradingEngine.current.episode.episodeCounters.strategies.value++ } function closeStrategy(exitType) { @@ -58,11 +60,11 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng function updateEnds() { if (tradingEngine.current.strategy.status.value === 'Open') { tradingEngine.current.strategy.end.value = tradingEngine.current.candle.end.value - tradingEngine.current.strategy.endRate.value = tradingEngine.current.candle.min.value + tradingEngine.current.strategy.endRate.value = tradingEngine.current.candle.close.value } } - function updateStatus() { + function resetTradingEngineDataStructure() { if (tradingEngine.current.strategy.status.value === 'Closed') { resetStrategy() }