Stages Plotted
This commit is contained in:
1 parent
ff0dd09dc7
commit
b0add9b805
9 files changed
+271
-153
No files matched your search
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user