508 lines
29 KiB
JavaScript
508 lines
29 KiB
JavaScript
exports.newFoundationsFunctionLibrariesDataDependenciesFunctions = function () {
|
|
/*
|
|
This module contains the functions that will allow you to load in memory
|
|
the data files which a process depends on, and later build the
|
|
data structures that will allow users to write conditions and formulas
|
|
using these data structures.
|
|
*/
|
|
const MODULE_NAME = "Data Dependency Function"
|
|
|
|
let thisObject = {
|
|
processSingleFiles: processSingleFiles,
|
|
processMarketFiles: processMarketFiles,
|
|
processDailyFiles: processDailyFiles,
|
|
buildDataStructures: buildDataStructures
|
|
}
|
|
|
|
return thisObject
|
|
|
|
async function processSingleFiles(
|
|
processIndex,
|
|
dataFiles,
|
|
multiTimeFrameDataFiles,
|
|
dataDependenciesModule
|
|
) {
|
|
|
|
/*
|
|
We will iterate through all the exchanges and markets involved.
|
|
*/
|
|
let exchangeList = Array.from(dataDependenciesModule.filters.exchange.list.keys())
|
|
let marketList = Array.from(dataDependenciesModule.filters.market.list.keys())
|
|
|
|
for (let e = 0; e < exchangeList.length; e++) {
|
|
let currentExchange = exchangeList[e]
|
|
for (let m = 0; m < marketList.length; m++) {
|
|
let currentMarket = marketList[m]
|
|
|
|
dataFiles = new Map()
|
|
|
|
for (let dependencyIndex = 0; dependencyIndex < dataDependenciesModule.curatedDependencyNodeArray.length; dependencyIndex++) {
|
|
let dependency = dataDependenciesModule.curatedDependencyNodeArray[dependencyIndex]
|
|
let datasetModule = dataDependenciesModule.dataSetsModulesArray[dependencyIndex]
|
|
|
|
if (datasetModule.node.config.codeName !== "Single-File") {
|
|
continue
|
|
}
|
|
|
|
if (datasetModule.exchange !== currentExchange) {
|
|
continue
|
|
}
|
|
|
|
if (datasetModule.market !== currentMarket) {
|
|
continue
|
|
}
|
|
|
|
if (dataDependenciesModule.filters.exchange.timeFrames.get(datasetModule.exchange + '-' + datasetModule.market + '-' + datasetModule.product + '-' + 'atAnyTimeFrame') !== true) {
|
|
/*
|
|
If we can not find the current data set is used at the current time
|
|
frame we will skip this file.
|
|
*/
|
|
continue
|
|
}
|
|
|
|
let fileName = "Data.json"
|
|
let filePath = datasetModule.node.parentNode.config.codeName + '/' + datasetModule.node.config.codeName
|
|
|
|
/* We cut the async calls via callBacks at this point, so as to have a clearer code upstream */
|
|
let response = await TS.projects.foundations.utilities.miscellaneousFunctions.asyncGetDatasetFile(datasetModule, filePath, fileName)
|
|
|
|
if (response.err.message === 'File does not exist.') {
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] File not Found. This process will wait until you run your Data Mining and this file is created. File = " + filePath + '/' + fileName)
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] Your strategy depends on the dataset " + dependency.name + '.')
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] The reason that it depends on this dataset is becuase in one of your condition's Javascript Code node, you have written an expression that references this dataset. If you don't want to depend on this dataset, just locate that code and remove the mention.")
|
|
return false
|
|
}
|
|
|
|
if (response.err.result !== TS.projects.foundations.globals.standardResponses.DEFAULT_OK_RESPONSE.result) {
|
|
throw (response.err)
|
|
}
|
|
|
|
let dataFile = JSON.parse(response.text)
|
|
dataFiles.set(dependency.id, dataFile)
|
|
}
|
|
|
|
let mapKey = currentExchange + '-' + currentMarket + '-' + "Single Files"
|
|
multiTimeFrameDataFiles.set(mapKey, dataFiles)
|
|
}
|
|
}
|
|
}
|
|
|
|
async function processMarketFiles(
|
|
processIndex,
|
|
dataFiles,
|
|
multiTimeFrameDataFiles,
|
|
dataDependenciesModule,
|
|
currentTimeFrame,
|
|
userDefinedTimeFrame,
|
|
initialDatetime,
|
|
finalDatetime
|
|
) {
|
|
/*
|
|
We do market files first since if the simulation is run on daily files, there will
|
|
be a loop to get each of those files and we do not need that loop to reload market files.
|
|
*/
|
|
|
|
/*
|
|
We will iterate through all the exchanges and markets involved.
|
|
*/
|
|
let exchangeList = Array.from(dataDependenciesModule.filters.exchange.list.keys())
|
|
let marketList = Array.from(dataDependenciesModule.filters.market.list.keys())
|
|
|
|
for (let e = 0; e < exchangeList.length; e++) {
|
|
let currentExchange = exchangeList[e]
|
|
for (let m = 0; m < marketList.length; m++) {
|
|
let currentMarket = marketList[m]
|
|
/*
|
|
We will iterate through all posible timeFrames.
|
|
*/
|
|
for (let n = 0; n < TS.projects.foundations.globals.timeFrames.marketTimeFramesArray().length; n++) {
|
|
const timeFrame = TS.projects.foundations.globals.timeFrames.marketTimeFramesArray()[n][0]
|
|
const timeFrameLabel = TS.projects.foundations.globals.timeFrames.marketTimeFramesArray()[n][1]
|
|
|
|
dataFiles = new Map()
|
|
|
|
/* Current Time Frame detection */
|
|
if (userDefinedTimeFrame === timeFrameLabel) {
|
|
currentTimeFrame.value = TS.projects.foundations.globals.timeFrames.marketTimeFramesArray()[n][0]
|
|
currentTimeFrame.label = TS.projects.foundations.globals.timeFrames.marketTimeFramesArray()[n][1]
|
|
}
|
|
|
|
/* Loop across the list of curated dependencies */
|
|
for (let dependencyIndex = 0; dependencyIndex < dataDependenciesModule.curatedDependencyNodeArray.length; dependencyIndex++) {
|
|
let dependency = dataDependenciesModule.curatedDependencyNodeArray[dependencyIndex]
|
|
let datasetModule = dataDependenciesModule.dataSetsModulesArray[dependencyIndex]
|
|
|
|
if (dependency.referenceParent.config.codeName !== "Multi-Time-Frame-Market") {
|
|
continue
|
|
}
|
|
|
|
if (datasetModule.exchange !== currentExchange) {
|
|
continue
|
|
}
|
|
|
|
if (datasetModule.market !== currentMarket) {
|
|
continue
|
|
}
|
|
|
|
if (dataDependenciesModule.filters.exchange.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 (!(userDefinedTimeFrame === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
|
|
continue
|
|
}
|
|
if (currentExchange !== dataDependenciesModule.defaultExchange || currentMarket !== dataDependenciesModule.defaultMarket) {
|
|
continue
|
|
}
|
|
}
|
|
|
|
let fileName = "Data.json"
|
|
let filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel
|
|
|
|
/* We cut the async calls via callBacks at this point, so as to have a clearer code upstream */
|
|
let response = await TS.projects.foundations.utilities.miscellaneousFunctions.asyncGetDatasetFile(datasetModule, filePath, fileName)
|
|
|
|
if (response.err.message === 'File does not exist.') {
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] File not Found. This process will wait until you run your Data Mining and this file is created. File = " + filePath + '/' + fileName)
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] Your strategy depends on the dataset " + dependency.name + '.')
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] The reason that it depends on this dataset is becuase in one of your condition's Javascript Code node, you have written an expression that references this dataset. If you don't want to depend on this dataset, just locate that code and remove the mention.")
|
|
return false
|
|
}
|
|
|
|
if (response.err.result !== TS.projects.foundations.globals.standardResponses.DEFAULT_OK_RESPONSE.result) {
|
|
throw (response.err)
|
|
}
|
|
|
|
let dataFile = JSON.parse(response.text)
|
|
let trimmedDataFile = trimDataFile(dataFile, datasetModule.node.parentNode.record)
|
|
dataFiles.set(dependency.id, trimmedDataFile)
|
|
|
|
function trimDataFile(dataFile, recordDefinition) {
|
|
/*
|
|
Here we will discard all the records in a file that are outside of the current time range.
|
|
We will include the las element previous to the begining of the time range. This is needed
|
|
because during the simulation, the current Time Frame is not the open one, but the previous to
|
|
the open, and if we do not include the previous to the initial datetime there will be no
|
|
current objects at the begining of the simulation for many time frames.
|
|
*/
|
|
let beginIndex
|
|
let endIndex
|
|
let result = []
|
|
for (let i = 0; i < recordDefinition.properties.length; i++) {
|
|
let property = recordDefinition.properties[i]
|
|
if (property.config.codeName === 'begin') {
|
|
beginIndex = i
|
|
}
|
|
if (property.config.codeName === 'end') {
|
|
endIndex = i
|
|
}
|
|
}
|
|
for (let i = 0; i < dataFile.length; i++) {
|
|
let dataRecord = dataFile[i]
|
|
let begin = dataRecord[beginIndex]
|
|
let end = dataRecord[endIndex]
|
|
/*
|
|
We will allow 4 objects before the initial datetime in order to allow formulas with 4 .previous
|
|
not to be undefined.
|
|
|
|
-1 because we need the previous closed element
|
|
*/
|
|
if (end + timeFrame * 4 < initialDatetime - 1) { continue }
|
|
if (begin > finalDatetime) { continue }
|
|
result.push(dataRecord)
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
let mapKey = currentExchange + '-' + currentMarket + '-' + TS.projects.foundations.globals.timeFrames.marketTimeFramesArray()[n][1]
|
|
multiTimeFrameDataFiles.set(mapKey, dataFiles)
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
async function processDailyFiles(
|
|
processIndex,
|
|
dataFiles,
|
|
multiTimeFrameDataFiles,
|
|
dataDependenciesModule,
|
|
currentTimeFrame,
|
|
userDefinedTimeFrame,
|
|
processDate
|
|
) {
|
|
/* Telling the world we are alive and doing well and which date we are processing right now. */
|
|
let processingDateString = processDate.getUTCFullYear() + '-' + SA.projects.foundations.utilities.miscellaneousFunctions.pad(processDate.getUTCMonth() + 1, 2) + '-' + SA.projects.foundations.utilities.miscellaneousFunctions.pad(processDate.getUTCDate(), 2)
|
|
TS.projects.foundations.functionLibraries.processFunctions.processHeartBeat(processIndex, processingDateString, undefined, "Running...")
|
|
|
|
/*
|
|
We will iterate through all the exchanges and markets involved.
|
|
*/
|
|
let exchangeList = Array.from(dataDependenciesModule.filters.exchange.list.keys())
|
|
let marketList = Array.from(dataDependenciesModule.filters.market.list.keys())
|
|
|
|
for (let e = 0; e < exchangeList.length; e++) {
|
|
let currentExchange = exchangeList[e]
|
|
for (let m = 0; m < marketList.length; m++) {
|
|
let currentMarket = marketList[m]
|
|
/*
|
|
We will iterate through all posible timeFrames.
|
|
*/
|
|
for (let n = 0; n < TS.projects.foundations.globals.timeFrames.dailyTimeFramesArray().length; n++) {
|
|
const timeFrameLabel = TS.projects.foundations.globals.timeFrames.dailyTimeFramesArray()[n][1]
|
|
|
|
if (TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.framework.validtimeFrames !== undefined) {
|
|
let validPeriod = false
|
|
for (let i = 0; i < TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.framework.validtimeFrames.length; i++) {
|
|
let period = TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.config.framework.validtimeFrames[i]
|
|
if (period === timeFrameLabel) { validPeriod = true }
|
|
}
|
|
if (validPeriod === false) {
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (userDefinedTimeFrame === timeFrameLabel) {
|
|
currentTimeFrame.value = TS.projects.foundations.globals.timeFrames.dailyTimeFramesArray()[n][0]
|
|
currentTimeFrame.label = TS.projects.foundations.globals.timeFrames.dailyTimeFramesArray()[n][1]
|
|
}
|
|
|
|
dataFiles = new Map()
|
|
|
|
/*
|
|
We will iterate through all dependencies, in order to load the
|
|
files that later will end up at the chart data structure.
|
|
*/
|
|
for (let dependencyIndex = 0; dependencyIndex < dataDependenciesModule.curatedDependencyNodeArray.length; dependencyIndex++) {
|
|
let dependency = dataDependenciesModule.curatedDependencyNodeArray[dependencyIndex]
|
|
let datasetModule = dataDependenciesModule.dataSetsModulesArray[dependencyIndex]
|
|
|
|
if (dependency.referenceParent.config.codeName !== "Multi-Time-Frame-Daily") {
|
|
continue
|
|
}
|
|
|
|
if (datasetModule.exchange !== currentExchange) {
|
|
continue
|
|
}
|
|
|
|
if (datasetModule.market !== currentMarket) {
|
|
continue
|
|
}
|
|
|
|
if (dataDependenciesModule.filters.exchange.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 (!(userDefinedTimeFrame === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
|
|
continue
|
|
}
|
|
if (currentExchange !== dataDependenciesModule.defaultExchange || currentMarket !== dataDependenciesModule.defaultMarket) {
|
|
continue
|
|
}
|
|
}
|
|
|
|
/*
|
|
We will need to fetch the data of the current day and the previous day, in order for .previous properties in conditions and formulas to work well.
|
|
*/
|
|
let previousDate = new Date(processDate.valueOf() - SA.projects.foundations.globals.timeConstants.ONE_DAY_IN_MILISECONDS)
|
|
let currentDate = new Date(processDate.valueOf())
|
|
|
|
let previousFile = await getDataFileFromDate(previousDate)
|
|
if (previousFile === false) { return false }
|
|
let currentFile = await getDataFileFromDate(currentDate)
|
|
if (currentFile === false) { return false }
|
|
let bothFiles = previousFile.concat(currentFile)
|
|
dataFiles.set(dependency.id, bothFiles)
|
|
|
|
async function getDataFileFromDate(dataFileDate) {
|
|
|
|
let dateForPath = dataFileDate.getUTCFullYear() + '/' + SA.projects.foundations.utilities.miscellaneousFunctions.pad(dataFileDate.getUTCMonth() + 1, 2) + '/' + SA.projects.foundations.utilities.miscellaneousFunctions.pad(dataFileDate.getUTCDate(), 2)
|
|
let filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel + "/" + dateForPath
|
|
let fileName = "Data.json"
|
|
|
|
/* We cut the async calls via callBacks at this point, so as to have a clearer code upstream */
|
|
let response = await TS.projects.foundations.utilities.miscellaneousFunctions.asyncGetDatasetFile(datasetModule, filePath, fileName)
|
|
|
|
if (response.err.message === 'File does not exist.') {
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] File not Found. This process will wait until you run your Data Mining and this file is created. File = " + filePath + '/' + fileName)
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] Your strategy depends on the dataset " + dependency.name + '.')
|
|
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
|
|
"[ERROR] The reason that it depends on this dataset is becuase in one of your condition's Javascript Code node, you have written an expression that references this dataset. If you don't want to depend on this dataset, just locate that code and remove the mention.")
|
|
return false
|
|
}
|
|
if (response.err.result !== TS.projects.foundations.globals.standardResponses.DEFAULT_OK_RESPONSE.result) {
|
|
throw (response.err)
|
|
}
|
|
|
|
return JSON.parse(response.text)
|
|
}
|
|
}
|
|
let mapKey = currentExchange + '-' + currentMarket + '-' + TS.projects.foundations.globals.timeFrames.dailyTimeFramesArray()[n][1]
|
|
multiTimeFrameDataFiles.set(mapKey, dataFiles)
|
|
}
|
|
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
function buildDataStructures(
|
|
processIndex,
|
|
dataDependenciesModule,
|
|
multiTimeFrameDataFiles,
|
|
currentTimeFrame,
|
|
chart,
|
|
market,
|
|
exchange,
|
|
callBackFunction
|
|
) {
|
|
/* Fisrt Phase: Validations */
|
|
let mainDependency = {}
|
|
/*
|
|
THe first thing we do is to build an array of all the
|
|
declared dependencies of the Bot Process.
|
|
*/
|
|
let dataDependencies = TS.projects.foundations.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processDependencies, 'Data Dependency')
|
|
/*
|
|
Then we will filter out declared dependencies that are
|
|
not referencing nodes currently present at the workspace.
|
|
This will allow the user to have less Data Mines loaded at
|
|
the workspace that the ones that a the Bot process depends on.
|
|
*/
|
|
dataDependencies = TS.projects.foundations.utilities.nodeFunctions.filterOutNodeWihtoutReferenceParentFromNodeArray(dataDependencies)
|
|
/*
|
|
We will run some validations to prevent starting the process
|
|
if all needed config and nodes are not present.
|
|
*/
|
|
if (TS.projects.foundations.functionLibraries.singleMarketFunctions.validateDataDependencies(processIndex, dataDependencies, callBackFunction) !== true) { return }
|
|
/*
|
|
Next we will build an array of output datasets of this process.
|
|
We are not going to use it right now, but later down the line,
|
|
we do it just to be able to validate that all nodes and config
|
|
are ok before letting this provess run too far.
|
|
*/
|
|
let outputDatasets = TS.projects.foundations.utilities.nodeFunctions.nodeBranchToArray(TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.processOutput, 'Output Dataset')
|
|
/*
|
|
Here we check that all output datasets configs are ok.
|
|
*/
|
|
if (TS.projects.foundations.functionLibraries.singleMarketFunctions.validateOutputDatasets(processIndex, outputDatasets, callBackFunction) !== true) { return }
|
|
|
|
/* Second Phase: Bilding the chart data structure */
|
|
|
|
/*
|
|
This phase is about transforming the inputs into a format,
|
|
or data structure that can be used in Javascript Code and
|
|
Formula nodes to access Indicator's data.
|
|
*/
|
|
|
|
let exchangeList = Array.from(dataDependenciesModule.filters.exchange.list.keys())
|
|
let marketList = Array.from(dataDependenciesModule.filters.market.list.keys())
|
|
|
|
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.foundations.globals.timeFrames.marketTimeFramesArray().length; j++) {
|
|
let timeFrameLabel = TS.projects.foundations.globals.timeFrames.marketTimeFramesArray()[j][1]
|
|
let dataFiles = multiTimeFrameDataFiles.get(currentExchange + '-' + currentMarket + '-' + timeFrameLabel)
|
|
let products = {}
|
|
|
|
if (dataFiles !== undefined && dataFiles.size > 0) {
|
|
TS.projects.foundations.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame.value)
|
|
|
|
let propertyName = 'at' + timeFrameLabel.replace('-', '')
|
|
addProducs(propertyName, products)
|
|
}
|
|
}
|
|
|
|
/* Daily Files */
|
|
for (let j = 0; j < TS.projects.foundations.globals.timeFrames.dailyTimeFramesArray().length; j++) {
|
|
let timeFrameLabel = TS.projects.foundations.globals.timeFrames.dailyTimeFramesArray()[j][1]
|
|
let dataFiles = multiTimeFrameDataFiles.get(currentExchange + '-' + currentMarket + '-' + timeFrameLabel)
|
|
let products = {}
|
|
|
|
if (dataFiles !== undefined && dataFiles.size > 0) {
|
|
TS.projects.foundations.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame.value)
|
|
|
|
let propertyName = 'at' + timeFrameLabel.replace('-', '')
|
|
addProducs(propertyName, products)
|
|
}
|
|
}
|
|
|
|
/* Single Files */
|
|
{
|
|
let dataFiles = multiTimeFrameDataFiles.get(currentExchange + '-' + currentMarket + '-' + 'Single Files')
|
|
let products = {}
|
|
|
|
if (dataFiles !== undefined && dataFiles.size > 0) {
|
|
TS.projects.foundations.functionLibraries.singleMarketFunctions.inflateDatafiles(processIndex, dataFiles, dataDependencies, products, mainDependency, currentTimeFrame.value)
|
|
|
|
let propertyName = 'atAnyTimeFrame'
|
|
addProducs(propertyName, products)
|
|
}
|
|
}
|
|
|
|
function addProducs(propertyName, products) {
|
|
/*
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |