From 2eb96dc048689240de0ae08ebaea4d18a59591a5 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 2 Feb 2021 13:25:42 +0100 Subject: [PATCH] Implementation finished, chart, market and exchange data structures available to conditions and formulas. --- .../Low-Frequency-Trading/TradingOutput.js | 11 +- .../Low-Frequency-Trading/TradingProcess.js | 150 +++++++++++++----- .../TradingSimulation.js | 8 +- .../Low-Frequency-Trading/TradingSystem.js | 20 ++- .../TS/Process-Modules/DataDependencies.js | 12 +- 5 files changed, 149 insertions(+), 52 deletions(-) diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOutput.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOutput.js index c6b2f28ca..fb3c06aa4 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOutput.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingOutput.js @@ -26,7 +26,14 @@ exports.newSuperalgosBotModulesTradingOutput = function (processIndex) { } - async function start(chart, timeFrame, timeFrameLabel, tradingProcessDate) { + async function start( + chart, + exchange, + market, + timeFrame, + timeFrameLabel, + tradingProcessDate + ) { try { if (timeFrame > TS.projects.superalgos.globals.timeFrames.dailyFilePeriods()[0][0]) { @@ -73,6 +80,8 @@ exports.newSuperalgosBotModulesTradingOutput = function (processIndex) { await tradingSimulationModuleObject.runSimulation( chart, + exchange, + market, outputDatasetsMap, writeFiles ) diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingProcess.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingProcess.js index 7c3170064..9011001b5 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingProcess.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingProcess.js @@ -14,7 +14,7 @@ let statusDependencies let dataDependenciesModule let dataFiles = new Map() - let multiPeriodDataFiles = new Map() + let multiTimeFrameDataFiles = new Map() let fileStorage = TS.projects.superalgos.taskModules.fileStorage.newFileStorage(processIndex) TS.projects.superalgos.globals.processModuleObjects.MODULE_OBJECTS_BY_PROCESS_INDEX_MAP.get(processIndex).TRADING_ENGINE_MODULE_OBJECT = TS.projects.superalgos.botModules.tradingEngine.newSuperalgosBotModulesTradingEngine(processIndex) let tradingOutputModuleObject = TS.projects.superalgos.botModules.tradingOutput.newSuperalgosBotModulesTradingOutput(processIndex) @@ -47,7 +47,7 @@ tradingOutputModuleObject = undefined dataFiles = undefined - multiPeriodDataFiles = undefined + multiTimeFrameDataFiles = undefined statusDependencies = undefined dataDependenciesModule = undefined fileStorage = undefined @@ -115,10 +115,11 @@ return } /* - This is the Data Structure used at the Simulation with all indicator data. - We start creating it right here. + These are the Data Structures used by end users at Conditions Code or Formulas. */ let chart = {} + let market = {} + let exchange = {} /* Here we check if we need to get Daily Files or not. As an optimization, when we are running on a Time Frame of 1hs or above, we are not going to load @@ -133,7 +134,7 @@ data structure that will be used in user-defied conditions and formulas. */ TS.projects.superalgos.functionLibraries.sessionFunctions.sessionHeartBeat(processIndex, undefined, undefined, 'Waking up') - buildCharts(chart) + buildDataStructures(chart) if (checkThereAreCandles(chart) === true) { TS.projects.superalgos.functionLibraries.sessionFunctions.sessionHeartBeat(processIndex, undefined, undefined, 'Running') @@ -172,7 +173,7 @@ With all the indicators data files loaded, we will build the chart object data structure that will be used in user-defied conditions and formulas. */ - buildCharts(chart) + buildDataStructures(chart) /* The process of generating the output includes the trading simulation. */ @@ -209,7 +210,7 @@ */ callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE) - function checkThereAreCandles(chart) { + function checkThereAreCandles() { let sessionParameters = TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.tradingParameters let propertyName = 'at' + sessionParameters.timeFrame.config.label.replace('-', '') let candles = chart[propertyName].candles @@ -373,7 +374,7 @@ } let mapKey = "Single Files" - multiPeriodDataFiles.set(mapKey, dataFiles) + multiTimeFrameDataFiles.set(mapKey, dataFiles) } async function processMarketFiles() { @@ -472,7 +473,7 @@ } let mapKey = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[n][1] - multiPeriodDataFiles.set(mapKey, dataFiles) + multiTimeFrameDataFiles.set(mapKey, dataFiles) } return true } @@ -569,7 +570,7 @@ } } let mapKey = TS.projects.superalgos.globals.timeFrames.dailyFilePeriods()[n][1] - multiPeriodDataFiles.set(mapKey, dataFiles) + multiTimeFrameDataFiles.set(mapKey, dataFiles) } return true } @@ -600,7 +601,7 @@ } } - function buildCharts(chart) { + function buildDataStructures() { /* Fisrt Phase: Validations */ let mainDependency = {} /* @@ -639,47 +640,108 @@ or data structure that can be used in Javascript Code and Formula nodes to access Indicator's data. */ - for (let j = 0; j < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length; j++) { - let timeFrameLabel = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[j][1] - let dataFiles = multiPeriodDataFiles.get(timeFrameLabel) - let products = {} - if (dataFiles !== undefined) { - TS.projects.superalgos.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame) + let exchangeList = Array.from(dataDependenciesModule.filters.exchange.list.keys()) + let marketList = Array.from(dataDependenciesModule.filters.market.list.keys()) - let propertyName = 'at' + timeFrameLabel.replace('-', '') - chart[propertyName] = products + for (let e = 0; e < exchangeList.length; e++) { + let currentExchange = exchangeList[e] + for (let m = 0; m < marketList.length; m++) { + let currentMarket = marketList[m] + let splittedMarket = currentMarket.split('-') + let baseAsset = splittedMarket[0] + let quotedAsset = splittedMarket[1] + + /* Market Files */ + for (let j = 0; j < TS.projects.superalgos.globals.timeFrames.marketFilesPeriods().length; j++) { + let timeFrameLabel = TS.projects.superalgos.globals.timeFrames.marketFilesPeriods()[j][1] + let dataFiles = multiTimeFrameDataFiles.get(timeFrameLabel) + let products = {} + + if (dataFiles !== undefined) { + TS.projects.superalgos.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame) + + let propertyName = 'at' + timeFrameLabel.replace('-', '') + addProducs(propertyName) + } + } + + /* Daily Files */ + for (let j = 0; j < TS.projects.superalgos.globals.timeFrames.dailyFilePeriods().length; j++) { + let timeFrameLabel = TS.projects.superalgos.globals.timeFrames.dailyFilePeriods()[j][1] + let dataFiles = multiTimeFrameDataFiles.get(timeFrameLabel) + let products = {} + + if (dataFiles !== undefined) { + TS.projects.superalgos.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame) + + let propertyName = 'at' + timeFrameLabel.replace('-', '') + addProducs(propertyName) + } + } + + /* Single Files */ + let dataFiles = multiTimeFrameDataFiles.get('Single Files') + let products = {} + + if (dataFiles !== undefined) { + TS.projects.superalgos.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame) + + let propertyName = 'atAnyTimeFrame' + addProducs(propertyName) + } + + function addProducs(propertyName) { + /* + The chart data structure allow users to simplify the syntax when they are using + the default exchange and the default market. + */ + if (currentExchange === dataDependenciesModule.defaultExchange && currentMarket === dataDependenciesModule.defaultMarket) { + chart[propertyName] = products + } + /* + The market data structure allow users to simplify the syntax when they are using + the default exchange. + */ + if (currentExchange === dataDependenciesModule.defaultExchange) { + if (market[baseAsset] === undefined) { + market[baseAsset] = {} + } + if (market[baseAsset][quotedAsset] === undefined) { + market[baseAsset][quotedAsset] = {} + } + if (market[baseAsset][quotedAsset].chart === undefined) { + market[baseAsset][quotedAsset].chart = {} + } + market[baseAsset][quotedAsset].chart[propertyName] = products + } + + if (exchange[currentExchange] === undefined) { + exchange[currentExchange] = {} + } + if (exchange[currentExchange].market === undefined) { + exchange[currentExchange].market = {} + } + if (exchange[currentExchange].market[baseAsset] === undefined) { + exchange[currentExchange].market[baseAsset] = {} + } + if (exchange[currentExchange].market[baseAsset][quotedAsset] === undefined) { + exchange[currentExchange].market[baseAsset][quotedAsset] = {} + } + if (exchange[currentExchange].market[baseAsset][quotedAsset].chart === undefined) { + exchange[currentExchange].market[baseAsset][quotedAsset].chart = {} + } + exchange[currentExchange].market[baseAsset][quotedAsset].chart[propertyName] = products + } } } - - for (let j = 0; j < TS.projects.superalgos.globals.timeFrames.dailyFilePeriods().length; j++) { - let timeFrameLabel = TS.projects.superalgos.globals.timeFrames.dailyFilePeriods()[j][1] - let dataFiles = multiPeriodDataFiles.get(timeFrameLabel) - let products = {} - - if (dataFiles !== undefined) { - TS.projects.superalgos.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame) - - let propertyName = 'at' + timeFrameLabel.replace('-', '') - chart[propertyName] = products - } - } - - /* Single Files */ - let dataFiles = multiPeriodDataFiles.get('Single Files') - let products = {} - - if (dataFiles !== undefined) { - TS.projects.superalgos.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame) - - let propertyName = 'atAnyTimeFrame' - chart[propertyName] = products - } } - async function generateOutput(chart) { + async function generateOutput() { await tradingOutputModuleObject.start( chart, + market, + exchange, currentTimeFrame, currentTimeFrameLabel, tradingProcessDate diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSimulation.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSimulation.js index 0c941284b..a4c95762f 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSimulation.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSimulation.js @@ -17,6 +17,8 @@ exports.newSuperalgosBotModulesTradingSimulation = function (processIndex) { async function runSimulation( chart, + exchange, + market, outputDatasetsMap, writeFiles, ) { @@ -146,7 +148,11 @@ exports.newSuperalgosBotModulesTradingSimulation = function (processIndex) { positionChartAtCurrentCandle() /* The chart was recalculated based on the current candle. */ - tradingSystemModuleObject.updateChart(chart) + tradingSystemModuleObject.updateChart( + chart, + exchange, + market + ) /* Do the stuff needed previous to the run like diff --git a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSystem.js b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSystem.js index fbc9c9dea..baff85703 100644 --- a/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSystem.js +++ b/Projects/Superalgos/TS/Bot-Modules/Trading-Bot/Low-Frequency-Trading/TradingSystem.js @@ -13,7 +13,14 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) { finalize: finalize } + /* + These 3 are the main data structures available to users + when writing conditions and formulas. + */ let chart + let exchange + let market + let tradingSystem let tradingEngine let sessionParameters @@ -115,6 +122,8 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) { tradingStagesModuleObject = undefined chart = undefined + exchange = undefined + market = undefined tradingSystem.conditions = undefined tradingSystem.formulas = undefined @@ -151,8 +160,15 @@ exports.newSuperalgosBotModulesTradingSystem = function (processIndex) { tradingSystem.announcements = [] } - function updateChart(pChart) { - chart = pChart // We need chat to be a local object accessible from conditions and formulas. + function updateChart(pChart, pExchange, pMarket) { + /* + We need these 3 data structures to be a local objects + accessible while evaluating conditions and formulas. + */ + chart = pChart + exchange = pExchange + market = pMarket + tradingStagesModuleObject.updateChart(pChart) } diff --git a/Projects/Superalgos/TS/Process-Modules/DataDependencies.js b/Projects/Superalgos/TS/Process-Modules/DataDependencies.js index 66ab8552e..cc77da285 100644 --- a/Projects/Superalgos/TS/Process-Modules/DataDependencies.js +++ b/Projects/Superalgos/TS/Process-Modules/DataDependencies.js @@ -21,6 +21,8 @@ let thisObject = { filters: undefined, + defaultExchange: undefined, + defaultMarket: undefined, curatedDependencyNodeArray: undefined, dataSetsModulesArray: [], initialize: initialize, @@ -101,13 +103,13 @@ At our filter structure, we will add the Task default exchange and market. This will help us lateer to build other structures in a generic way. */ - let defaultExchange = TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName - let defautMarket = + thisObject.defaultExchange = TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + thisObject.defautMarket = TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "-" + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName - thisObject.filters.exchange.list.set(defaultExchange, true) - thisObject.filters.exchange.markets.set(defaultExchange + '-' + defautMarket, true) + thisObject.filters.exchange.list.set(thisObject.defaultExchange, true) + thisObject.filters.exchange.markets.set(thisObject.defaultExchange + '-' + thisObject.defautMarket, true) thisObject.filters.market.list.set(true) /* For each dependency declared at the curatedDependencyNodeArray, we will initialize a DataSet as part of this initialization process. @@ -243,6 +245,8 @@ thisObject.dataSetsModulesArray = undefined thisObject.curatedDependencyNodeArray = undefined thisObject.filters = undefined + thisObject.defaultExchange = undefined + thisObject.defaultMarket = undefined bot = undefined } }