diff --git a/LowFrequencyTrading/TradingEngine.js b/LowFrequencyTrading/TradingEngine.js index 5bbce94c2..a230f5d4d 100644 --- a/LowFrequencyTrading/TradingEngine.js +++ b/LowFrequencyTrading/TradingEngine.js @@ -6,6 +6,7 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) { const MODULE_NAME = 'Trading Engine' let thisObject = { mantain: mantain, + reset: reset, getNodeById: getNodeById, cloneValues: cloneValues, setCurrentCandle: setCurrentCandle, @@ -46,6 +47,10 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) { updateDistanceToEventsCounters() } + function reset() { + + } + function getNodeById(NodeId) { return nodesMap.get(NodeId) } diff --git a/LowFrequencyTrading/TradingEpisode.js b/LowFrequencyTrading/TradingEpisode.js index a3207a285..a654de03a 100644 --- a/LowFrequencyTrading/TradingEpisode.js +++ b/LowFrequencyTrading/TradingEpisode.js @@ -5,6 +5,7 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin const MODULE_NAME = 'Trading Episode' let thisObject = { mantain: mantain, + reset: reset, openEpisode: openEpisode, updateExitType: updateExitType, closeEpisode: closeEpisode, @@ -33,12 +34,15 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin } function mantain() { - resetTradingEngineDataStructure() updateCounters() updateStatistics() updateEnds() } + function reset() { + resetTradingEngineDataStructure() + } + function openEpisode() { /* This function is called each time the simulation starts. That does not mean the Episode diff --git a/LowFrequencyTrading/TradingExecution.js b/LowFrequencyTrading/TradingExecution.js index 95a929bcf..eb3cb4bdf 100644 --- a/LowFrequencyTrading/TradingExecution.js +++ b/LowFrequencyTrading/TradingExecution.js @@ -6,6 +6,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE let thisObject = { mantain: mantain, + reset: reset, runExecution: runExecution, initialize: initialize, finalize: finalize @@ -41,6 +42,10 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE tradingOrdersModule.mantain() } + function reset() { + tradingOrdersModule.reset() + } + async function runExecution( executionNode, tradingEngineStage diff --git a/LowFrequencyTrading/TradingOrders.js b/LowFrequencyTrading/TradingOrders.js index 835427233..cb38120c4 100644 --- a/LowFrequencyTrading/TradingOrders.js +++ b/LowFrequencyTrading/TradingOrders.js @@ -6,6 +6,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM let thisObject = { mantain: mantain, + reset: reset, checkOrders: checkOrders, initialize: initialize, finalize: finalize @@ -45,6 +46,14 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM } function mantain() { + mantainReset(true, false) + } + + function reset() { + mantainReset(false, true) + } + + function mantainReset(mantain, reset) { if (tradingEngine.current.strategy.index.value === tradingEngine.current.strategy.index.config.initialValue) { return } @@ -53,42 +62,46 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM stageNode = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value].openStage executionNode = stageNode.openExecution - mantainExecutionNode(executionNode, tradingEngine.current.strategyOpenStage.status.value) + processExecutionNode(executionNode, tradingEngine.current.strategyOpenStage.status.value) stageNode = tradingSystem.tradingStrategies[tradingEngine.current.strategy.index.value].closeStage executionNode = stageNode.closeExecution - mantainExecutionNode(executionNode, tradingEngine.current.strategyCloseStage.status.value) + processExecutionNode(executionNode, tradingEngine.current.strategyCloseStage.status.value) - function mantainExecutionNode(executionNode, stageStatus) { + function processExecutionNode(executionNode, stageStatus) { - mantainExecutionAlgorithms(executionNode) + preocessExecutionAlgorithms(executionNode) - function mantainExecutionAlgorithms(executionNode) { + function preocessExecutionAlgorithms(executionNode) { for (let i = 0; i < executionNode.executionAlgorithms.length; i++) { let executionAlgorithm = executionNode.executionAlgorithms[i] - mantainOrders(executionAlgorithm.marketBuyOrders) - mantainOrders(executionAlgorithm.marketSellOrders) - mantainOrders(executionAlgorithm.limitBuyOrders) - mantainOrders(executionAlgorithm.limitSellOrders) + processOrders(executionAlgorithm.marketBuyOrders) + processOrders(executionAlgorithm.marketSellOrders) + processOrders(executionAlgorithm.limitBuyOrders) + processOrders(executionAlgorithm.limitSellOrders) } } - function mantainOrders(orders) { + function processOrders(orders) { for (let i = 0; i < orders.length; i++) { let tradingSystemOrder = orders[i] - if (tradingSystemOrder.referenceParent === undefined) { continue } + if (tradingSystemOrder.referenceParent === undefined) { + badDefinitionUnhandledException(undefined, 'tradingSystemOrder.referenceParent === undefined', tradingSystemOrder) + } let tradingEngineOrder = tradingEngineModule.getNodeById(tradingSystemOrder.referenceParent.id) - try { - if (tradingEngineOrder.status === undefined) { continue } - } catch (err) { - console.log(err.stack) + + if (tradingEngineOrder.status === undefined) { + badDefinitionUnhandledException(undefined, 'tradingEngineOrder.status === undefined', tradingEngineOrder) } - - updateCounters(tradingEngineOrder) - updateEnds(tradingEngineOrder) - updateStatistics(tradingEngineOrder) - resetTradingEngineDataStructure(tradingEngineOrder, tradingSystemOrder, stageStatus) + if (mantain === true) { + updateCounters(tradingEngineOrder) + updateEnds(tradingEngineOrder) + updateStatistics(tradingEngineOrder) + } + if (reset === true) { + resetTradingEngineDataStructure(tradingEngineOrder, tradingSystemOrder, stageStatus) + } } } } @@ -216,7 +229,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM /* Create Order Procedure */ tradingEngineOrder.status.value = 'Open' tradingEngineOrder.identifier.value = global.UNIQUE_ID() - tradingEngineOrder.begin.value = tradingEngine.current.episode.candle.begin.value + tradingEngineOrder.begin.value = tradingEngine.current.episode.candle.end.value tradingEngineOrder.end.value = tradingEngine.current.episode.candle.end.value tradingEngineOrder.serialNumber.value = tradingEngine.current.episode.episodeCounters.orders.value tradingEngineOrder.orderName.value = tradingSystemOrder.name diff --git a/LowFrequencyTrading/TradingPosition.js b/LowFrequencyTrading/TradingPosition.js index 076c262e8..86016d7f4 100644 --- a/LowFrequencyTrading/TradingPosition.js +++ b/LowFrequencyTrading/TradingPosition.js @@ -5,6 +5,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng const MODULE_NAME = 'Trading Position' let thisObject = { mantain: mantain, + reset: reset, openPosition: openPosition, closingPosition: closingPosition, closePosition: closePosition, @@ -39,18 +40,21 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng } function mantain() { - resetTradingEngineDataStructure() updateCounters() updateEnds() } + function reset() { + resetTradingEngineDataStructure() + } + function openPosition(situationName) { /* Recording the opening at the Trading Engine Data Structure */ tradingEngine.current.position.status.value = 'Open' tradingEngine.current.position.serialNumber.value = tradingEngine.current.episode.episodeCounters.positions.value tradingEngine.current.position.identifier.value = global.UNIQUE_ID() - tradingEngine.current.position.begin.value = tradingEngine.current.episode.candle.begin.value + tradingEngine.current.position.begin.value = tradingEngine.current.episode.candle.end.value tradingEngine.current.position.beginRate.value = tradingEngine.current.episode.candle.close.value tradingEngine.current.position.positionBaseAsset.beginBalance.value = tradingEngine.current.episode.episodeBaseAsset.balance.value tradingEngine.current.position.positionQuotedAsset.beginBalance.value = tradingEngine.current.episode.episodeQuotedAsset.balance.value diff --git a/LowFrequencyTrading/TradingSimulation.js b/LowFrequencyTrading/TradingSimulation.js index acd5d239d..db5133c52 100644 --- a/LowFrequencyTrading/TradingSimulation.js +++ b/LowFrequencyTrading/TradingSimulation.js @@ -137,16 +137,41 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, UTILIT /* The chart was recalculated based on the current candle. */ tradingSystemModule.updateChart(chart) - /* Do the stuff needed previous to the run */ + /* + Do the stuff needed previous to the run like + Episode Counters and Statistics update + */ tradingSystemModule.mantain() - - /* Episode Counters and Statistics update */ tradingEpisodeModule.mantain() - - /* Run your maintaince procedure */ tradingEngineModule.mantain() - /* Run one cycle of the Trading System*/ + /* Reset Data Structures */ + tradingSystemModule.reset() + tradingEpisodeModule.reset() + tradingEngineModule.reset() + + /* + Run the first cycle of the Trading System. In this first cycle we + give some room so that orders can be canceled or filled and we can + write those records into the output memory. + */ + await tradingSystemModule.run() + + /* Add new records to the process output */ + tradingRecordsModule.appendRecords() + + /* Reset Data Structures */ + tradingSystemModule.reset() + tradingEpisodeModule.reset() + tradingEngineModule.reset() + + /* + Run the second cycle of the Trading System. During this second run + some new orders might be created at slots freed up during the first + run. This allows for example for an Limit Order to be cancelled during the + first run, and the same Limit Order definition to spawn a new order + without the need to wait until the next candle. + */ await tradingSystemModule.run() controlLoop() diff --git a/LowFrequencyTrading/TradingStages.js b/LowFrequencyTrading/TradingStages.js index 1f19fd31b..e6735e3b9 100644 --- a/LowFrequencyTrading/TradingStages.js +++ b/LowFrequencyTrading/TradingStages.js @@ -6,6 +6,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM let thisObject = { updateChart: updateChart, mantain: mantain, + reset: reset, runTriggerStage: runTriggerStage, runOpenStage: runOpenStage, runManageStage: runManageStage, @@ -88,11 +89,18 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM tradingStrategyModule.mantain() tradingExecutionModule.mantain() - resetTradingEngineDataStructure() updateCounters() updateEnds() } + function reset() { + tradingPositionModule.reset() + tradingStrategyModule.reset() + tradingExecutionModule.reset() + + resetTradingEngineDataStructure() + } + function runTriggerStage() { /* We check if we will be triggering on, off or taking position. @@ -1017,7 +1025,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM function openStage(stage) { /* Recording the opening at the Trading Engine Data Structure */ - stage.begin.value = tradingEngine.current.episode.candle.begin.value + stage.begin.value = tradingEngine.current.episode.candle.end.value stage.beginRate.value = tradingEngine.current.episode.candle.close.value stage.end.value = tradingEngine.current.episode.candle.end.value } diff --git a/LowFrequencyTrading/TradingStrategy.js b/LowFrequencyTrading/TradingStrategy.js index 87216fc29..5225f705d 100644 --- a/LowFrequencyTrading/TradingStrategy.js +++ b/LowFrequencyTrading/TradingStrategy.js @@ -5,6 +5,7 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng const MODULE_NAME = 'Trading Strategy' let thisObject = { mantain: mantain, + reset: reset, openStrategy: openStrategy, closeStrategy: closeStrategy, initialize: initialize, @@ -24,16 +25,19 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng } function mantain() { - resetTradingEngineDataStructure() updateCounters() updateEnds() } + function reset() { + resetTradingEngineDataStructure() + } + function openStrategy(index, situationName, strategyName) { tradingEngine.current.strategy.status.value = 'Open' tradingEngine.current.strategy.serialNumber.value = tradingEngine.current.episode.episodeCounters.strategies.value tradingEngine.current.strategy.identifier.value = global.UNIQUE_ID() - tradingEngine.current.strategy.begin.value = tradingEngine.current.episode.candle.begin.value + tradingEngine.current.strategy.begin.value = tradingEngine.current.episode.candle.end.value tradingEngine.current.strategy.end.value = tradingEngine.current.episode.candle.end.value tradingEngine.current.strategy.beginRate.value = tradingEngine.current.episode.candle.min.value diff --git a/LowFrequencyTrading/TradingSystem.js b/LowFrequencyTrading/TradingSystem.js index b84db7f45..ae6c839a5 100644 --- a/LowFrequencyTrading/TradingSystem.js +++ b/LowFrequencyTrading/TradingSystem.js @@ -6,6 +6,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM const MODULE_NAME = 'Trading System' let thisObject = { mantain: mantain, + reset: reset, run: run, updateChart: updateChart, initialize: initialize, @@ -97,19 +98,19 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM } function mantain() { - reset() - tradingStagesModule.mantain() + tradingSystem.highlights = [] + tradingSystem.errors = [] + tradingSystem.values = [] + tradingSystem.status = [] + tradingSystem.progress = [] + tradingSystem.running = [] + tradingSystem.announcements = [] - function reset() { - /* This function helps reset data structures at every cycle of the simulation loop/=. */ - tradingSystem.highlights = [] - tradingSystem.errors = [] - tradingSystem.values = [] - tradingSystem.status = [] - tradingSystem.progress = [] - tradingSystem.running = [] - tradingSystem.announcements = [] - } + tradingStagesModule.mantain() + } + + function reset() { + tradingStagesModule.reset() } function updateChart(pChart) {