From 74e80cb43c88977b15f2231195ea1ae38e2107f6 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 2 Feb 2021 11:19:15 +0100 Subject: [PATCH] Data Dependencies and Dataset implementation done --- .../Low-Frequency-Trading/TradingProcess.js | 7 +- .../TS/Process-Modules/DataDependencies.js | 51 ++++++------ .../Superalgos/TS/Process-Modules/Dataset.js | 2 + .../Function-Libraries/DependenciesFilter.js | 38 +++++---- .../TradingSessionFunctions.js | 81 +++++++++++++++---- 5 files changed, 119 insertions(+), 60 deletions(-) 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 62be039f2..3e86e4c9a 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 @@ -400,7 +400,12 @@ continue } - if (dataDependenciesModule.isItAChartDepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) { + if (dataDependenciesModule.filters.timeFrames.get(datasetModule.exchange, datasetModule.market, datasetModule.product, timeFrameLabel) !== true) { + /* + If we can not find the current data set is used at the current time + frame we will skip this file, unless we are in the only special + case that we are retrieving candles. + */ if (!(TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.tradingParameters.timeFrame.config.label === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) { continue } diff --git a/Projects/Superalgos/TS/Process-Modules/DataDependencies.js b/Projects/Superalgos/TS/Process-Modules/DataDependencies.js index 02811f93d..aff88fdc1 100644 --- a/Projects/Superalgos/TS/Process-Modules/DataDependencies.js +++ b/Projects/Superalgos/TS/Process-Modules/DataDependencies.js @@ -29,18 +29,14 @@ } thisObject.filters = { - chart: { - list: new Map(), - products: new Map() - }, market: { - list: new Map(), - products: new Map() + list: new Map() }, exchange: { list: new Map(), markets: new Map(), - products: new Map() + products: new Map(), + timeFrames: new Map() } } @@ -88,15 +84,12 @@ these maps in an Array format, and here we will just convert them to Maps, that is how we need them. */ - arrayToMap(receivedDependencyFilters.chart.list, thisObject.filters.chart.list) - arrayToMap(receivedDependencyFilters.chart.products, thisObject.filters.chart.products) - arrayToMap(receivedDependencyFilters.market.list, thisObject.filters.market.list) - arrayToMap(receivedDependencyFilters.market.products, thisObject.filters.market.products) arrayToMap(receivedDependencyFilters.exchange.list, thisObject.filters.exchange.list) arrayToMap(receivedDependencyFilters.exchange.markets, thisObject.filters.exchange.markets) arrayToMap(receivedDependencyFilters.exchange.products, thisObject.filters.exchange.products) + arrayToMap(receivedDependencyFilters.exchange.timeFrames, thisObject.filters.exchange.timeFrames) function arrayToMap(array, map) { for (let i = 0; i < array.length; i++) { @@ -168,32 +161,36 @@ function addDataSets(exchange, market) { for (let i = 0; i < thisObject.curatedDependencyNodeArray.length; i++) { + let dataDependency = thisObject.curatedDependencyNodeArray[i] + if (receivedDependencyFilters !== undefined) { /* If we received a Dependency Filter from the UI, we will make these excta checks before instantiating a Data Set Module. */ - if (exchange === defaultExchange && market === defautMarket) { - + if (dataDependency.referenceParent === undefined) { + continue } - - // Validaciones para llegar hasta el producto: datasetModule.node.parentNode.config.singularVariableName - // Que el producto este en el filtro - // Necesito un filtro exchange mercado producto que venga desde la UI - // Para eso la funcion que los arma tiene que saber cual es el default Exchange y el Defautl market. - // Quizas vuele el concepto de filtro de chart , de market y de exchange separados - - // dentro del dataset que se valide que el network node que llega hasta el producto pase por el market y exchange - - if (thisObject.filters.exchange.markets.get(exchange + '-' + market) === true) { - addDataSets(exchange, market) + if (dataDependency.referenceParent.parentNode === undefined) { + continue } + if (dataDependency.referenceParent.parentNode.config.singularVariableName === undefined) { + continue + } + /* + This is the product related to this Data Dependency, as the user would type it + at a Condition or Formula and appear at the UI provided filter. + */ + let product = dataDependency.referenceParent.parentNode.config.singularVariableName + + if (thisObject.filters.products.get(exchange + '-' + market + '-' + product) !== true) { + continue + } + addDataSets(exchange, market) } - - let dataSetModule = TS.projects.superalgos.processModules.dataset.newSuperalgosProcessModulesDataset(processIndex) - dataSetModule.initialize(exchange, market, thisObject.curatedDependencyNodeArray[i], onInitilized) + dataSetModule.initialize(exchange, market, dataDependency, onInitilized) function onInitilized(err, wasInitialized) { diff --git a/Projects/Superalgos/TS/Process-Modules/Dataset.js b/Projects/Superalgos/TS/Process-Modules/Dataset.js index d0a664010..3c8ca1199 100644 --- a/Projects/Superalgos/TS/Process-Modules/Dataset.js +++ b/Projects/Superalgos/TS/Process-Modules/Dataset.js @@ -11,6 +11,7 @@ exports.newSuperalgosProcessModulesDataset = function (processIndex) { networkNode: undefined, exchange: undefined, market: undefined, + product: undefined, initialize: initialize, finalize: finalize, getTextFile: getTextFile, @@ -81,6 +82,7 @@ exports.newSuperalgosProcessModulesDataset = function (processIndex) { /* Now we will see where do we need to fetch this data from. */ let network = TS.projects.superalgos.globals.taskConstants.NETWORK_NODE let productDefinition = thisObject.node.parentNode + thisObject.product = productDefinition.config.singularVariableName /* We will find the networkNode that leads to this Product Definition diff --git a/Projects/Superalgos/UI/Function-Libraries/DependenciesFilter.js b/Projects/Superalgos/UI/Function-Libraries/DependenciesFilter.js index e79fc7fac..5caff8d29 100644 --- a/Projects/Superalgos/UI/Function-Libraries/DependenciesFilter.js +++ b/Projects/Superalgos/UI/Function-Libraries/DependenciesFilter.js @@ -18,34 +18,27 @@ function newSuperalgosFunctionLibraryDependenciesFilter() { return thisObject - function createDependencyFilter(node) { + function createDependencyFilter(tradingSystem, defaultExchange, defaultMarket) { let filters = { - chart: { - list: new Map(), - products: new Map() - }, market: { - list: new Map(), - products: new Map() + list: new Map() }, exchange: { list: new Map(), markets: new Map(), - products: new Map() + products: new Map(), + timeFrames: new Map() } } - recursiveFilter(node) + recursiveFilter(tradingSystem) /* Transform the Map into arrays */ - filters.chart.list = Array.from(filters.chart.list.keys()) - filters.chart.products = Array.from(filters.chart.products.keys()) - filters.market.list = Array.from(filters.market.list.keys()) - filters.market.products = Array.from(filters.market.products.keys()) filters.exchange.list = Array.from(filters.exchange.list.keys()) filters.exchange.markets = Array.from(filters.exchange.markets.keys()) filters.exchange.products = Array.from(filters.exchange.products.keys()) + filters.exchange.timeFrames = Array.from(filters.exchange.timeFrames.keys()) return filters @@ -124,8 +117,12 @@ function newSuperalgosFunctionLibraryDependenciesFilter() { if (timeFrame !== 'atAnyTimeFrame') { timeFrame = timeFrame.substring(2, 4) + '-' + timeFrame.substring(4, 7) } - filters.chart.products.set(timeFrame + '-' + product, true) - filters.chart.list.set(timeFrame, true) + filters.market.list.set(defaultMarket, true) + + filters.exchange.timeFrames.set(defaultExchange + '-' + defaultMarket + '-' + product + '-' + timeFrame, true) + filters.exchange.products.set(defaultExchange + '-' + defaultMarket + '-' + product, true) + filters.exchange.markets.set(defaultExchange + '-' + defaultMarket, true) + filters.exchange.list.set(defaultExchange, true) } /* The second kind of instruction we will handle are the ones @@ -144,8 +141,12 @@ function newSuperalgosFunctionLibraryDependenciesFilter() { if (timeFrame !== 'atAnyTimeFrame') { timeFrame = timeFrame.substring(2, 4) + '-' + timeFrame.substring(4, 7) } - filters.market.products.set(baseAsset + '-' + quotedAsset + '-' + timeFrame + '-' + product, true) filters.market.list.set(baseAsset + '-' + quotedAsset, true) + + filters.exchange.timeFrames.set(defaultExchange + '-' + baseAsset + '-' + quotedAsset + '-' + product + '-' + timeFrame, true) + filters.exchange.products.set(defaultExchange + '-' + baseAsset + '-' + quotedAsset + '-' + product, true) + filters.exchange.markets.set(defaultExchange + '-' + baseAsset + '-' + quotedAsset, true) + filters.exchange.list.set(defaultExchange, true) } /* The third kind of instruction we will handle are the ones @@ -165,7 +166,10 @@ function newSuperalgosFunctionLibraryDependenciesFilter() { if (timeFrame !== 'atAnyTimeFrame') { timeFrame = timeFrame.substring(2, 4) + '-' + timeFrame.substring(4, 7) } - filters.exchange.products.set(exchange + '-' + baseAsset + '-' + quotedAsset + '-' + timeFrame + '-' + product, true) + filters.market.list.set(baseAsset + '-' + quotedAsset, true) + + filters.exchange.timeFrames.set(exchange + '-' + baseAsset + '-' + quotedAsset + '-' + product + '-' + timeFrame, true) + filters.exchange.products.set(exchange + '-' + baseAsset + '-' + quotedAsset + '-' + product, true) filters.exchange.markets.set(exchange + '-' + baseAsset + '-' + quotedAsset, true) filters.exchange.list.set(exchange, true) } diff --git a/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js b/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js index 2b5733ba2..3d64eca5a 100644 --- a/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js +++ b/Projects/Superalgos/UI/Function-Libraries/TradingSessionFunctions.js @@ -1,6 +1,6 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { thisObject = { - syncronizeSessionWithBackEnd: syncronizeSessionWithBackEnd, + syncronizeSessionWithBackEnd: syncronizeSessionWithBackEnd, runSession: runSession, stopSession: stopSession } @@ -8,7 +8,7 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { return thisObject function syncronizeSessionWithBackEnd(node) { - let networkNode = validations(node) + let networkNode = validations(node).networkNode if (networkNode === undefined) { /* Nodes that do not belong to a network can not get ready. */ return @@ -27,7 +27,7 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { function onStatus(message) { eventsServerClient.stopListening(key, eventSubscriptionIdOnStatus, node.id) - if (message.event.status === 'Trading Session Runnning' ) { + if (message.event.status === 'Trading Session Runnning') { node.payload.uiObject.menu.internalClick('Run Trading Session') } } @@ -37,7 +37,8 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { } function runSession(node, resume, callBackFunction) { - let networkNode = validations(node) + let validationsResult = validations(node) + let networkNode = validationsResult.networkNode if (networkNode === undefined) { /* This means that the validations failed. */ callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) @@ -123,7 +124,14 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { let session = UI.projects.superalgos.functionLibraries.protocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath) - let dependencyFilter = UI.projects.superalgos.functionLibraries.dependenciesFilter.createDependencyFilter(node.tradingSystemReference.payload.referenceParent) + let defaultExchange = validationsResult.exchange.config.codeName + let defaultMarket = validationsResult.market.baseAsset.payload.referenceParent.config.codeName + '-' + validationsResult.market.quotedAsset.payload.referenceParent.config.codeName + + let dependencyFilter = UI.projects.superalgos.functionLibraries.dependenciesFilter.createDependencyFilter( + defaultExchange, + defaultMarket, + node.tradingSystemReference.payload.referenceParent + ) /* Raise event to run the session */ let event = { @@ -147,13 +155,13 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { } function stopSession(node, callBackFunction) { - let networkNode = validations(node) + let networkNode = validations(node).networkNode if (networkNode === undefined) { /* This means that the validations failed. */ callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) return } - + let eventsServerClient = UI.projects.superalgos.spaces.designSpace.workspace.eventsServerClients.get(networkNode.id) let key = node.name + '-' + node.type + '-' + node.id @@ -163,6 +171,9 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { } function validations(node) { + + let result = {} + if (node.payload.parentNode === undefined) { node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be able to run.') return @@ -183,34 +194,34 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { return } - let taskManager = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode + result.taskManager = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode - if (taskManager.payload.parentNode === undefined) { + if (result.taskManager.payload.parentNode === undefined) { node.payload.uiObject.setErrorMessage('Session needs to be inside Mine Tasks.') return } - if (taskManager.payload.parentNode.payload.parentNode === undefined) { + if (result.taskManager.payload.parentNode.payload.parentNode === undefined) { node.payload.uiObject.setErrorMessage('Session needs to be inside Market Tasks.') return } - if (taskManager.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + if (result.taskManager.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { node.payload.uiObject.setErrorMessage('Session needs to be inside Exchange Tasks.') return } - if (taskManager.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + if (result.taskManager.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { node.payload.uiObject.setErrorMessage('Session needs to be inside a Testing or Production Trading Tasks.') return } - if (taskManager.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + if (result.taskManager.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { node.payload.uiObject.setErrorMessage('Session needs to be inside a Network Node.') return } - let networkNode = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(taskManager, 'Network Node', undefined, true, false, true, false) + result.networkNode = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(result.taskManager, 'Network Node', undefined, true, false, true, false) if (node.tradingSystemReference === undefined) { node.payload.uiObject.setErrorMessage('Session needs a child Trading System Reference.') @@ -231,6 +242,46 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() { node.payload.uiObject.setErrorMessage('Trading Engine Reference needs to reference a Trading Engine.') return } - return networkNode + + if (result.taskManager.payload.parentNode.payload.parentNode.payload.referenceParent === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to have a Default Market.') + return + } + + result.market = result.taskManager.payload.parentNode.payload.parentNode.payload.referenceParent + + if (market.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Default Market needs to be a child of Exchange Markets.') + return + } + + if (market.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Exchange Markets neeed to be a child of Crypto Exchange.') + return + } + + if (market.baseAsset === undefined) { + node.payload.uiObject.setErrorMessage('Default Market needs to have a Base Asset.') + return + } + + if (market.quotedAsset === undefined) { + node.payload.uiObject.setErrorMessage('Default Market needs to have a Quoted Asset.') + return + } + + if (market.baseAsset.payload.referenceParent === undefined) { + node.payload.uiObject.setErrorMessage('Market Base Asset needs to reference an Asset.') + return + } + + if (market.quotedAsset.payload.referenceParent === undefined) { + node.payload.uiObject.setErrorMessage('Market Quoted Asset needs to reference an Asset.') + return + } + + result.exchange = market.payload.parentNode.payload.parentNode + + return result.networkNode } }