Async Await implementation at Trading Process

This commit is contained in:
Luis Fernando Molina committed 2020-08-18 14:31:52 +02:00
1 parent ea047363af
commit fdbffef52e
17 files changed
+902 -905

No files matched your search

@@ -19,11 +19,11 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
thisObject = undefined
}
function runSimulation(
async function runSimulation(
chart,
outputDatasetsMap,
callback,
callBackFunction) {
writeFiles,
) {
try {
let tradingSystem = bot.simulationState.tradingSystem
@@ -58,51 +58,54 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
let heartBeatDate
let previousHeartBeatDate
let firstLoopExecution = true
/*
Loop Initialization
*/
if (bot.FIRST_EXECUTION === false && tradingEngine.last.candle !== undefined) {
/* Estimate the Initial Candle based on the last candle saved at tradingEngine */
let firstBegin = candles[0].begin
let lastBegin = tradingEngine.last.candle.begin
let diff = lastBegin - firstBegin
let amount = diff / sessionParameters.timeFrame.config.value
initializeLoop()
tradingEngine.current.episode.candle.index.value = Math.trunc(amount) + 1 // Because we need to start from the next candle
if (tradingEngine.current.episode.candle.index.value < 0 || tradingEngine.current.episode.candle.index.value > candles.length - 1) {
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> Cannot resume simulation.')
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> tradingEngine.current.episode.candle.index.value = ' + tradingEngine.current.episode.candle.index.value)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> firstBegin = ' + firstBegin)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> lastBegin = ' + lastBegin)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> diff = ' + diff)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> amount = ' + amount)
function initializeLoop() {
if (bot.FIRST_EXECUTION === false && tradingEngine.last.candle !== undefined) {
/* Estimate the Initial Candle based on the last candle saved at tradingEngine */
let firstBegin = candles[0].begin
let lastBegin = tradingEngine.last.candle.begin
let diff = lastBegin - firstBegin
let amount = diff / sessionParameters.timeFrame.config.value
tradingEngine.current.episode.candle.index.value = Math.trunc(amount) + 1 // Because we need to start from the next candle
if (tradingEngine.current.episode.candle.index.value < 0 || tradingEngine.current.episode.candle.index.value > candles.length - 1) {
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> Cannot resume simulation.')
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> tradingEngine.current.episode.candle.index.value = ' + tradingEngine.current.episode.candle.index.value)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> firstBegin = ' + firstBegin)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> lastBegin = ' + lastBegin)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> diff = ' + diff)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> initializeLoop -> amount = ' + amount)
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
return
}
} else {
/* Estimate Initial Candle based on the timeRage configured for the session. */
let firstEnd = candles[0].end
let targetEnd = sessionParameters.timeRange.config.initialDatetime
let diff = targetEnd - firstEnd
let amount = diff / sessionParameters.timeFrame.config.value
tradingEngine.current.episode.candle.index.value = Math.trunc(amount)
if (tradingEngine.current.episode.candle.index.value < 0) { tradingEngine.current.episode.candle.index.value = 0 }
if (tradingEngine.current.episode.candle.index.value > candles.length - 1) {
/*
This will happen when the sessionParameters.timeRange.config.initialDatetime is beyond the last candle available,
meaning that the dataSet needs to be updated with more up-to-date data.
*/
tradingEngine.current.episode.candle.index.value = candles.length - 1
}
throw(global.DEFAULT_FAIL_RESPONSE)
return
}
} else {
/* Estimate Initial Candle based on the timeRage configured for the session. */
let firstEnd = candles[0].end
let targetEnd = sessionParameters.timeRange.config.initialDatetime
let diff = targetEnd - firstEnd
let amount = diff / sessionParameters.timeFrame.config.value
loop()
tradingEngine.current.episode.candle.index.value = Math.trunc(amount)
if (tradingEngine.current.episode.candle.index.value < 0) { tradingEngine.current.episode.candle.index.value = 0 }
if (tradingEngine.current.episode.candle.index.value > candles.length - 1) {
/*
This will happen when the sessionParameters.timeRange.config.initialDatetime is beyond the last candle available,
meaning that the dataSet needs to be updated with more up-to-date data.
*/
tradingEngine.current.episode.candle.index.value = candles.length - 1
}
}
async function loop() {
/*
Main Simulation Loop
*/
let breakLoop = false
for( let i = tradingEngine.current.episode.candle.index.value; i < candles.length; i++) {
tradingEngine.current.episode.candle.index.value = i
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Processing candle # ' + tradingEngine.current.episode.candle.index.value) }
let candle = candles[tradingEngine.current.episode.candle.index.value] // This is the current candle the Simulation is working at.
@@ -119,19 +122,8 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
firstLoopExecution = false
}
if (checkLastCandle() === false) {
closeEpisode('Last Candle Reached')
return
}
if (checkMinimunAndMaximunBalance() === false) {
closeEpisode('Min or Max Balance Reached')
return
}
if (checkInitialAndFinalDatetime() === false) {
controlLoop()
return
if (checkInitialDatetime() === false) {
continue
}
positionChartAtCurrentCandle()
@@ -178,75 +170,61 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
tradingEngineModule.setCurrentCycle('Second')
await tradingSystemModule.run()
controlLoop()
}
function controlLoop() {
/* Checking if we should continue processing this loop or not. */
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.')
updateEpisode('Session Stopped')
return
breakLoop = true
}
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.')
updateEpisode('Task Stopped')
return
breakLoop = true
}
if (tradingEngine.current.episode.candle.index.value + 1 < candles.length) {
/* Add new records to the process output */
tradingRecordsModule.appendRecords('Second')
tradingEngine.current.episode.candle.index.value++
/*
This will execute the next loop in the next iteration of the NodeJs event loop
allowing for other callbacks to be executed. It also prevents the error
'Maximum call stack size exceeded', since the call is not placed at the call stack.
*/
setImmediate(loop)
} else {
updateEpisode('All Candles Processed')
if (checkFinalDatetime() === false) {
closeEpisode('Final Datetime Reached')
breakLoop = true
}
if (checkLastCandle() === false) {
updateEpisode('All Available Candles Processed')
breakLoop = true
}
if (checkMinimunAndMaximunBalance() === false) {
closeEpisode('Min or Max Balance Reached')
breakLoop = true
}
/* Add new records to the process output */
tradingRecordsModule.appendRecords('Second')
if (breakLoop === true) {break}
}
tradingEngineModule.finalize()
tradingSystemModule.finalize()
tradingRecordsModule.finalize()
tradingEpisodeModule.finalize()
tradingEngineModule = undefined
tradingSystemModule = undefined
tradingRecordsModule = undefined
tradingEpisodeModule = undefined
await writeFiles()
function closeEpisode(exitType) {
tradingEpisodeModule.updateExitType(exitType)
tradingEpisodeModule.closeEpisode()
/* Add new records to the process output */
tradingRecordsModule.appendRecords('Second')
afterLoop()
}
function updateEpisode(exitType) {
tradingEpisodeModule.updateExitType(exitType)
/* Add new records to the process output */
tradingRecordsModule.appendRecords('Second')
afterLoop()
}
function afterLoop() {
tradingEngineModule.finalize()
tradingSystemModule.finalize()
tradingRecordsModule.finalize()
tradingEpisodeModule.finalize()
tradingEngineModule = undefined
tradingSystemModule = undefined
tradingRecordsModule = undefined
tradingEpisodeModule = undefined
callback()
}
function heartBeat() {
@@ -368,7 +346,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
} catch (err) {
logger.write(MODULE_NAME, '[ERROR] runSimulation -> getElement -> datasetName = ' + datasetName)
logger.write(MODULE_NAME, '[ERROR] runSimulation -> getElement -> err = ' + err.stack)
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
throw(global.DEFAULT_FAIL_RESPONSE)
}
}
@@ -379,7 +357,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
*/
if (bot.processingDailyFiles) { // We are processing Daily Files
let candlesPerDay = global.ONE_DAY_IN_MILISECONDS / sessionParameters.timeFrame.config.value
if (tradingEngine.current.episode.candle.index.value === candles.length - 1) {
if (tradingEngine.current.episode.candle.index.value + 1 === candles.length - 1) {
if ((candles.length < candlesPerDay) || (candles.length > candlesPerDay && candles.length < candlesPerDay * 2)) {
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
@@ -390,7 +368,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
}
}
} else { // We are processing Market Files
if (tradingEngine.current.episode.candle.index.value === candles.length - 1) {
if (tradingEngine.current.episode.candle.index.value + 1 === candles.length - 1) {
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
}
@@ -398,13 +376,18 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
return true
}
function checkInitialAndFinalDatetime() {
/* Here we check that the current candle is not outside of user-defined time range at the session parameters.*/
function checkInitialDatetime() {
/* Here we check that the current candle is not before the initial datetime defined at the session parameters.*/
if (tradingEngine.current.episode.candle.end.value < sessionParameters.timeRange.config.initialDatetime) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkInitialAndFinalDatetime -> Skipping Candle before the sessionParameters.timeRange.config.initialDatetime.') }
return false
}
if (tradingEngine.current.episode.candle.begin.value > sessionParameters.timeRange.config.finalDatetime) {
return true
}
function checkFinalDatetime() {
/* Here we check that the next candle is not after of the user-defined final datetime at the session parameters.*/
if (tradingEngine.current.episode.candle.begin.value + sessionParameters.timeFrame.config.value > sessionParameters.timeRange.config.finalDatetime) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> checkInitialAndFinalDatetime -> Skipping Candle after the sessionParameters.timeRange.config.finalDatetime.') }
return false
}
@@ -464,7 +447,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT
}
} catch (err) {
logger.write(MODULE_NAME, '[ERROR] runSimulation -> err = ' + err.stack)
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
throw(global.DEFAULT_FAIL_RESPONSE)
}
}
}