From 3ae0c647f42c8ef8c2f52053bbb7daf6bef5854a Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Thu, 3 Oct 2019 16:53:59 +0200 Subject: [PATCH] Processing Events to Run Sessions --- Context.js | 6 +-- MultiPeriod.js | 4 +- Root.js | 1 + TradingEngineProcessMainLoop.js | 88 ++++++++++++++++++++++++--------- server.js | 7 ++- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/Context.js b/Context.js index 0392beed2..6bb50a361 100644 --- a/Context.js +++ b/Context.js @@ -304,10 +304,10 @@ thisObject.executionHistory = []; - if (global.INITIAL_BALANCE_ASSET_A === undefined || global.INITIAL_BALANCE_ASSET_B === undefined) { throw new Error("Global Variables INITIAL_BALANCE_A and INITIAL_BALANCE_B cannot be undefined.") } + if (bot.VALUES_TO_USE.initialBalanceAssetA === undefined || bot.VALUES_TO_USE.initialBalanceAssetB === undefined) { throw new Error("Global Variables INITIAL_BALANCE_A and INITIAL_BALANCE_B cannot be undefined.") } - const INITIAL_BALANCE_A = Number(global.INITIAL_BALANCE_ASSET_A); - const INITIAL_BALANCE_B = Number(global.INITIAL_BALANCE_ASSET_B); + const INITIAL_BALANCE_A = Number(bot.VALUES_TO_USE.initialBalanceAssetA); + const INITIAL_BALANCE_B = Number(bot.VALUES_TO_USE.initialBalanceAssetB); thisObject.executionContext = { diff --git a/MultiPeriod.js b/MultiPeriod.js index e6e5eb155..a31e3870e 100644 --- a/MultiPeriod.js +++ b/MultiPeriod.js @@ -284,7 +284,7 @@ let dependencyIndex = 0; dataFiles = []; - if (global.DEFINITION.simulationParams.timePeriod === outputPeriodLabel) { + if (bot.VALUES_TO_USE.timePeriod === outputPeriodLabel) { currentTimePeriod = global.marketFilesPeriods[n][0]; currentOutputPeriodLabel = global.marketFilesPeriods[n][1]; } @@ -582,7 +582,7 @@ } } - if (global.DEFINITION.simulationParams.timePeriod === outputPeriodLabel) { + if (bot.VALUES_TO_USE.timePeriod === outputPeriodLabel) { currentTimePeriod = global.dailyFilePeriods[n][0]; currentOutputPeriodLabel = global.dailyFilePeriods[n][1]; } diff --git a/Root.js b/Root.js index 6dd38245d..cc459e242 100644 --- a/Root.js +++ b/Root.js @@ -174,6 +174,7 @@ botConfig.process = global.TASK_NODE.bot.processes[processIndex].code.process; botConfig.debug = {}; botConfig.processIndex = processIndex + botConfig.processNode = global.TASK_NODE.bot.processes[processIndex] /* Loop Counter */ diff --git a/TradingEngineProcessMainLoop.js b/TradingEngineProcessMainLoop.js index 83798826a..0bad0c65f 100644 --- a/TradingEngineProcessMainLoop.js +++ b/TradingEngineProcessMainLoop.js @@ -89,14 +89,41 @@ if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] run -> Entering function."); } - bot.enableCheckLoopHealth = true; + /* Check if there is a session */ + if (bot.processNode.session === undefined) { + parentLogger.write(MODULE_NAME, "[ERROR] run -> Cannot run without a Session."); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + /* Some initial values*/ + bot.enableCheckLoopHealth = true; let fixedTimeLoopIntervalHandle; global.STOP_PROCESSING = true; - global.SYSTEM_EVENT_HANDLER.listenToEvent('Cockpit-Restart-Button', 'Backstesting Started', undefined, undefined, undefined, startBackTesting) - global.SYSTEM_EVENT_HANDLER.listenToEvent('Cockpit-Restart-Button', 'Live-Trading Started', undefined, undefined, undefined, startLiveTrading) - global.SYSTEM_EVENT_HANDLER.listenToEvent('Cockpit-Restart-Button', 'Stop Requested', undefined, undefined, undefined, stopRequested) + /* Listen to event to start or stop the session. */ + + let key = 'Session' + '-' + bot.processNode.session.id + '-' + 'Events' + + global.SYSTEM_EVENT_HANDLER.listenToEvent(key, 'Run Session', undefined, undefined, undefined, runSession) + global.SYSTEM_EVENT_HANDLER.listenToEvent(key, 'Stop Session', undefined, undefined, undefined, stopSession) + + function runSession(message) { + switch (bot.processNode.session.type) { + case 'Backtesting Session': { + startBackTesting(message) + break + } + case 'Live Trading Session': { + startLiveTrading(message) + break + } + } + } + + function stopSession(message) { + global.STOP_PROCESSING = true + } function startBackTesting(message) { @@ -107,7 +134,7 @@ processConfig.framework.startDate.resumeExecution = false; global.STOP_PROCESSING = false bot.hasTheBotJustStarted = true - setValuesToUse() + setValuesToUse(message) const ONE_YEAR_IN_MILISECONDS = 365 * 24 * 60 * 60 * 1000 /* If we can not get for any reason the initial date of the backtest, we will start at present time. */ @@ -182,14 +209,18 @@ bot.multiPeriodDailyProcessDatetime = processConfig.framework.startDate.fixedDate global.STOP_PROCESSING = false bot.hasTheBotJustStarted = true - setValuesToUse() + setValuesToUse(message) } - function stopRequested() { - global.STOP_PROCESSING = true - } + function setValuesToUse(message) { + /* + Base on the information received we will determined which values ultimatelly are going to be used, + and once we do, they will become constants across the multiple loops executions. + */ + + bot.SESSION = JSON.parse(message.event.session) + bot.VALUES_TO_USE = {} - function setValuesToUse() { if (global.DEFINITION !== undefined) { let tradingSystem = global.DEFINITION.tradingSystem @@ -201,8 +232,8 @@ let code try { /* Default Value */ - global.INITIAL_BALANCE_ASSET_B = 0.001; - global.INITIAL_BALANCE_ASSET_A = 0 + bot.VALUES_TO_USE.initialBalanceAssetB = 0.001; + bot.VALUES_TO_USE.initialBalanceAssetA = 0 code = JSON.parse(tradingSystem.parameters.baseAsset.code); @@ -216,28 +247,41 @@ if (baseAsset === 'BTC') { // NOTE: POLONIEX, the only exchange working so far, has Asset A and B inverted. We need to fix this. if (code.initialBalance !== undefined) { - global.INITIAL_BALANCE_ASSET_B = code.initialBalance; - global.INITIAL_BALANCE_ASSET_A = 0 + bot.VALUES_TO_USE.initialBalanceAssetB = code.initialBalance; + bot.VALUES_TO_USE.initialBalanceAssetA = 0 } } else { if (code.initialBalance !== undefined) { - global.INITIAL_BALANCE_ASSET_A = code.initialBalance; - global.INITIAL_BALANCE_ASSET_B = 0 + bot.VALUES_TO_USE.initialBalanceAssetA = code.initialBalance; + bot.VALUES_TO_USE.initialBalanceAssetB = 0 } } } catch (err) { global.DEFINITION.tradingSystem.parameters.baseAsset.error = err.message - global.INITIAL_BALANCE_ASSET_A = 0 // default - global.INITIAL_BALANCE_ASSET_B = 0.001 // default + bot.VALUES_TO_USE.initialBalanceAssetA = 0 // default + bot.VALUES_TO_USE.initialBalanceAssetB = 0.001 // default } } - /* Decide which Time Period we are going to use. If a TimePeriod is explicity defined we replace the one which was sent on simulation params.*/ + /* Decide which Time Period we are going to use.*/ + /* This is the last fallback */ + bot.VALUES_TO_USE.timePeriod = global.DEFINITION.simulationParams.timePeriod + + /* Secondary option, if exists. */ if (tradingSystem.parameters.timePeriod !== undefined) { - global.DEFINITION.simulationParams.timePeriod = tradingSystem.parameters.timePeriod.code + bot.VALUES_TO_USE.timePeriod = tradingSystem.parameters.timePeriod.code + } + + /* Primary source of information, if it exists */ + if (bot.SESSION !== undefined) { + if (bot.SESSION.parameters !== undefined) { + if (bot.SESSION.parameters.timePeriod !== undefined) { + bot.VALUES_TO_USE.timePeriod = bot.SESSION.parameters.timePeriod.code + } + } } } } @@ -294,10 +338,10 @@ /* Checking if we should process this loop or not.*/ if (global.STOP_PROCESSING === true) { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> Waiting for Backtesting or Live Trade to be started."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> Waiting for " + bot.processNode.session.type + " " + bot.processNode.session.name + " to be started."); } console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) - + " Waiting for Backtesting or Live Trade to be started. "); + + " Waiting for " + bot.processNode.session.type + " " + bot.processNode.session.name + " to be started. "); global.SYSTEM_EVENT_HANDLER.raiseEvent('Jason-Multi-Period', 'Process Stopped') diff --git a/server.js b/server.js index 0b7f12a40..bdf6269dc 100644 --- a/server.js +++ b/server.js @@ -71,10 +71,11 @@ if (global.TASK_NODE !== undefined) { } else { // I use this section to debug in standalone mode. - let argument = ' {"type":"Task","name":"Runs Backtests, Fordwardtests & Live Trades ","bot":{"type":"Trading Engine","processes":[{"type":"Process","name":"Multi Period","code":{"team":"AAMasters","bot":"AAJason","process":"Multi-Period","repo":"AAJason-Trading-Engine-Bot"},"id":"4748c8c4-4d19-4076-96b2-e9c06524fbb3"}]},"id":"561bac18-fc78-464a-90c5-79fd821fc633"}' - /* charly */ argument = '{"type":"Task","name":"Brings Trades Records from the Exchange","bot":{"type":"Sensor","name":"Charly","processes":[{"type":"Process","name":"Live Trades","code":{"team":"AAMasters","bot":"AACharly","process":"Live-Trades"},"id":"5846ebc7-1979-4a80-9cc7-94bb4b8659dc"},{"type":"Process","name":"Hole Fixing","code":{"team":"AAMasters","bot":"AACharly","process":"Hole-Fixing"},"id":"31fc4f05-75d4-419a-9fb0-73e25e856f15"}]},"id":"5bfef4dc-54c1-44db-ace6-1ab27a86746e"}' + let argument = '{"type":"Task","name":"Runs Backtests, Fordwardtests & Live Trades ","bot":{"type":"Trading Engine","processes":[{"type":"Process","subType":"Trading Engine Process","name":"Multi Period","code":{"team":"AAMasters","bot":"AAJason","process":"Multi-Period","repo":"AAJason-Trading-Engine-Bot"},"session":{"type":"Backtesting Session","name":"New Backtesting Session","parameters":{"type":"Parameters","name":"Parameters","baseAsset":{"type":"Base Asset","name":"Base Asset","code":"{ \n\"name\": \"BTC\",\n\"initialBalance\": 0.001,\n\"minimumBalance\": 0.0001,\n\"maximumBalance\": 1\n}"},"timeRange":{"type":"Time Range","name":"Time Range","code":"{\n\"initialDatetime\": \"2019-09-15T00:00:00.000Z\",\n\"finalDatetime\": \"2019-09-30T00:00:00.000Z\"\n}"},"timePeriod":{"type":"Time Period","name":"Time Period","code":"01-hs"},"slippage":{"type":"Slippage","name":"Slippage","code":"{\n\"positionRate\": 0.1,\n\"stopLoss\": 0.1,\n\"takeProfit\": 0.1\n}"},"feeStructure":{"type":"Fee Structure","name":"Fee Structure","code":"{\n\"maker\": 0.15,\n\"taker\": 0.25\n}"}},"id":"1381b048-7795-4e60-84a4-cf02e7385ba1"},"id":"072065fc-a57c-439c-94cf-f3f9c901ed37"}]},"id":"cddc97dd-ca2d-4b14-95ce-f15b6149996f"}' + /* charly argument = '{"type":"Task","name":"Brings Trades Records from the Exchange","bot":{"type":"Sensor","name":"Charly","processes":[{"type":"Process","name":"Live Trades","code":{"team":"AAMasters","bot":"AACharly","process":"Live-Trades"},"id":"5846ebc7-1979-4a80-9cc7-94bb4b8659dc"},{"type":"Process","name":"Hole Fixing","code":{"team":"AAMasters","bot":"AACharly","process":"Hole-Fixing"},"id":"31fc4f05-75d4-419a-9fb0-73e25e856f15"}]},"id":"5bfef4dc-54c1-44db-ace6-1ab27a86746e"}' // olivia argument = '{"type":"Task","name":"Generates 1 min to 24 hs Candles & Volumes","bot":{"type":"Indicator","name":"Olivia","processes":[{"type":"Process","name":"Daily","code":{"team":"AAMasters","bot":"AAOlivia","process":"Multi-Period-Daily"},"id":"68cc8e1b-e94a-477e-82d0-15ecc9f1b9e2"},{"type":"Process","name":"Market","code":{"team":"AAMasters","bot":"AAOlivia","process":"Multi-Period-Market"},"id":"e1ac5e3d-d491-4e90-baf4-d4e5b71a8b1a"}]},"id":"efe36e05-75ea-41b5-8d92-c6b27635c834"}' // bruce argument = ' {"type":"Task","name":"Converts Trades into 1 min Candles & Volumes","bot":{"type":"Indicator","name":"Bruce","processes":[{"type":"Process","name":"New Process","code":{"team":"AAMasters","bot":"AABruce","process":"Single-Period-Daily"},"id":"e184744f-5de0-41c1-ad4c-36960f4ced90"}]},"id":"42758590-a7bd-4712-a5c9-80a3a820c5b3"}' + */ try { global.TASK_NODE = JSON.parse(argument) } catch (err) { @@ -141,8 +142,6 @@ global.EXIT_NODE_PROCESS = function exitProcess() { setTimeout(process.exit, 10000) // We will give 10 seconds to logs be written on file } -let notFirstSequence = false; - /* Setting up the global Event Handler */ const EVENT_HANDLER_MODULE = require('./SystemEventHandler.js');