Superalgos Beta 7, first commit.

This commit is contained in:
Luis Fernando Molina committed 2020-11-05 10:38:10 +01:00
1 parent c877072b7c
commit eb427eb146
63 files changed
+4339 -458

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

+1 -1
View File
@@ -65,7 +65,7 @@ try {
WEB_SERVER.initialize()
WEB_SERVER.run()
console.log("You are running Superalgos Beta 6 SP4.")
console.log("You are running Superalgos Beta 7: What's new? Multi-Project & Machine Learning Infrastructure is being implemented here.")
} catch (err) {
console.log('[ERROR] BackendServers -> Task Manager -> server -> Error = ' + err.stack)
+5 -5
View File
@@ -74,7 +74,7 @@ function newProductStorage(name) {
}
}
function initialize(dataMine, bot, session, product, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, callBackFunction) {
function initialize(mine, bot, session, product, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, callBackFunction) {
try {
datetime = pDatetime
timeFrame = pTimeFrame
@@ -90,7 +90,7 @@ function newProductStorage(name) {
dataSetsToLoad++
let marketFiles = newMarketFiles()
marketFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onMarketFileReady)
marketFiles.initialize(mine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onMarketFileReady)
thisObject.marketFiles.push(marketFiles)
}
break
@@ -99,7 +99,7 @@ function newProductStorage(name) {
dataSetsToLoad++
let dailyFiles = newDailyFiles()
dailyFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, onDailyFileReady)
dailyFiles.initialize(mine, bot, session, product, dataset, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, onDailyFileReady)
thisObject.dailyFiles.push(dailyFiles)
}
break
@@ -108,7 +108,7 @@ function newProductStorage(name) {
dataSetsToLoad++
let singleFile = newSingleFile()
singleFile.initialize(dataMine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onSingleFileReady)
singleFile.initialize(mine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onSingleFileReady)
thisObject.singleFile.push(singleFile)
}
break
@@ -117,7 +117,7 @@ function newProductStorage(name) {
dataSetsToLoad++
let fileSequences = newFileSequence()
fileSequences.initialize(dataMine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onFileSequenceReady)
fileSequences.initialize(mine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onFileSequenceReady)
thisObject.fileSequences.push(fileSequences)
}
break
+12 -7
View File
@@ -5,7 +5,7 @@ function getNodeDefinition(node) {
} else {
console.log('[Error] Could not get APP Scchema for project ' + node.project)
}
}
function dynamicDecimals(value, minDecimals) {
@@ -14,13 +14,18 @@ function dynamicDecimals(value, minDecimals) {
}
let decimals = 0
if (value < 1) { decimals = 2 }
if (Math.abs(Math.trunc(value * 100)) < 1) { decimals = 4 }
if (Math.abs(Math.trunc(value * 10000)) < 1) { decimals = 6 }
if (Math.abs(Math.trunc(value * 1000000)) < 1) { decimals = 8 }
if (Math.abs(Math.trunc(value * 100000000)) < 1) { decimals = 10 }
if (Math.abs(Math.trunc(value * 10000000000)) < 1) { value = 0; decimals = 0 }
if (decimals < minDecimals) {decimals = minDecimals}
if (Math.abs(Math.trunc(value * 10)) < 1) { decimals = 4 }
if (Math.abs(Math.trunc(value * 100)) < 1) { decimals = 5 }
if (Math.abs(Math.trunc(value * 1000)) < 1) { decimals = 6 }
if (Math.abs(Math.trunc(value * 10000)) < 1) { decimals = 7 }
if (Math.abs(Math.trunc(value * 100000)) < 1) { decimals = 8 }
if (Math.abs(Math.trunc(value * 1000000)) < 1) { decimals = 9 }
if (Math.abs(Math.trunc(value * 10000000)) < 1) { decimals = 10 }
if (Math.abs(Math.trunc(value * 100000000000)) < 1) { value = 0; decimals = 0 }
if (decimals < minDecimals) {decimals = minDecimals}
let returnValue = Number(value).toFixed(decimals)
return returnValue
}
+4 -4
View File
@@ -45,7 +45,7 @@ function newDailyFiles() {
}
}
function initialize(pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pDatetime, pTimeFrame, pHost, pPort, pEventsServerClient, callBackFunction) {
function initialize(pMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pDatetime, pTimeFrame, pHost, pPort, pEventsServerClient, callBackFunction) {
try {
callBackWhenFileReceived = callBackFunction
@@ -69,7 +69,7 @@ function newDailyFiles() {
function getDataRangeFile() {
/* First we will get the Data Range */
fileCloud.getFile(pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, true, undefined, onDataRangeReceived)
fileCloud.getFile(pMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, true, undefined, onDataRangeReceived)
function onDataRangeReceived(err, pFile) {
switch (err.result) {
@@ -109,7 +109,7 @@ function newDailyFiles() {
function getTimeFramesFile() {
/* First we will get the Data Range */
fileCloud.getFile(pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, undefined, true, onTimeFramesReceived)
fileCloud.getFile(pMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, undefined, true, onTimeFramesReceived)
function onTimeFramesReceived(err, pFile) {
switch (err.result) {
@@ -165,7 +165,7 @@ function newDailyFiles() {
let fileCursor = newFileCursor()
fileCursor.eventHandler = thisObject.eventHandler // We share our event handler with each file cursor, so that they can raise events there when files are changed.s
fileCursor.initialize(fileCloud, pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, periodName, periodTime, pDatetime, pTimeFrame, beginDateRange, endDateRange, pEventsServerClient, onInitialized)
fileCursor.initialize(fileCloud, pMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, periodName, periodTime, pDatetime, pTimeFrame, beginDateRange, endDateRange, pEventsServerClient, onInitialized)
function onInitialized(err) {
try {
switch (err.result) {
+7 -7
View File
@@ -21,12 +21,12 @@ function newFileCloud () {
fileStorage = newFileStorage(pHost, pPort)
}
function getFile (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, pTimeFrames, callBackFunction) {
function getFile (pMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, pTimeFrames, callBackFunction) {
try {
const MAX_RETRIES = 3
getFileRecursively(0, pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, pTimeFrames, callBackFunction)
getFileRecursively(0, pMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, pTimeFrames, callBackFunction)
function getFileRecursively (pRetryCounter, pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, pTimeFrames, callBackFunction) {
function getFileRecursively (pRetryCounter, pMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, pTimeFrames, callBackFunction) {
try {
let fileName
let filePath
@@ -78,7 +78,7 @@ function newFileCloud () {
if (fileName === undefined) {
logger.write('[ERROR] getFile -> getFileRecursively -> Inconsistant data. Check the following: ')
logger.write('[ERROR] getFile -> getFileRecursively -> pDataMine = ' + JSON.stringify(pDataMine))
logger.write('[ERROR] getFile -> getFileRecursively -> pMine = ' + JSON.stringify(pMine))
logger.write('[ERROR] getFile -> getFileRecursively -> pBot = ' + JSON.stringify(pBot))
logger.write('[ERROR] getFile -> getFileRecursively -> pDataset = ' + JSON.stringify(pDataset))
logger.write('[ERROR] getFile -> getFileRecursively -> pExchange = ' + JSON.stringify(pExchange))
@@ -93,8 +93,8 @@ function newFileCloud () {
filePath = filePath.replace('@QuotedAsset', pMarket.quotedAsset)
}
if (pDataMine !== undefined) {
filePath = filePath.replace('@DataMine', pDataMine.config.codeName)
if (pMine !== undefined) {
filePath = filePath.replace('@DataMine', pMine.config.codeName)
}
if (pBot !== undefined) {
@@ -161,7 +161,7 @@ function newFileCloud () {
if (ERROR_LOG === true) { logger.write('[ERROR] getFile -> getFileRecursively -> onFileReceived -> MAX_RETRIES = ' + MAX_RETRIES) }
if (ERROR_LOG === true) { logger.write('[ERROR] getFile -> getFileRecursively -> onFileReceived -> pRetryCounter = ' + pRetryCounter) }
getFileRecursively(pRetryCounter + 1, pDataMine, pBot, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, callBackFunction)
getFileRecursively(pRetryCounter + 1, pMine, pBot, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, callBackFunction)
return
} else {
if (ERROR_LOG === true) { logger.write('[ERROR] getFile -> getFileRecursively -> onFileReceived -> Could not get this file from storage. ') }
+8 -8
View File
@@ -25,7 +25,7 @@ function newFileCursor() {
let market
let exchange
let fileCloud
let dataMine
let mine
let bot
let session
let product
@@ -53,7 +53,7 @@ function newFileCursor() {
market = undefined
exchange = undefined
fileCloud = undefined
dataMine = undefined
mine = undefined
bot = undefined
session = undefined
product = undefined
@@ -77,7 +77,7 @@ function newFileCursor() {
function initialize(
pFileCloud,
pDataMine,
pMine,
pBot,
pSession,
pProduct,
@@ -96,7 +96,7 @@ function newFileCursor() {
market = pMarket
exchange = pExchange
fileCloud = pFileCloud
dataMine = pDataMine
mine = pMine
bot = pBot
session = pSession
product = pProduct
@@ -108,11 +108,11 @@ function newFileCursor() {
endDateRange = pEndDateRange
eventsServerClient = pEventsServerClient
let key = dataMine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + dataset.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
let key = mine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + dataset.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
let callerId = key + '-' + periodName + newUniqueId()
eventsServerClient.listenToEvent(key, 'Dataset Updated', undefined, callerId, onResponseDataSet, updateFiles)
key = dataMine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
key = mine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
callerId = key + '-' + periodName + newUniqueId()
eventsServerClient.listenToEvent(key, 'Data Range Updated', undefined, callerId, onResponseDataRange, updateDataRange)
@@ -168,7 +168,7 @@ function newFileCursor() {
dateString = targetDate.getUTCFullYear() + '-' + pad(targetDate.getUTCMonth() + 1, 2) + '-' + pad(targetDate.getUTCDate(), 2)
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, periodName, targetDate, undefined, undefined, undefined, onFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, periodName, targetDate, undefined, undefined, undefined, onFileReceived)
function onFileReceived(err, file) {
try {
@@ -468,7 +468,7 @@ function newFileCursor() {
if (thisObject.files.get(dateString) === undefined) {
// We dont reload files we already have.
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, periodName, targetDate, undefined, undefined, undefined, onFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, periodName, targetDate, undefined, undefined, undefined, onFileReceived)
} else {
controlLoop()
}
+9 -9
View File
@@ -20,7 +20,7 @@ function newFileSequence () {
let files = new Map()
let maxSequence = -1 // This is replaced by the content of the sequence file, which contains an index that starts on zero. In the case that the sequence file is not found the default value is -1 so when you add 1 it gives you the amount of files in the sequence, zero.
let market
let dataMine
let mine
let bot
let session
let dataset
@@ -48,7 +48,7 @@ function newFileSequence () {
files = undefined
maxSequence = undefined
market = undefined
dataMine = undefined
mine = undefined
bot = undefined
session = undefined
dataset = undefined
@@ -62,7 +62,7 @@ function newFileSequence () {
}
function initialize (
pDataMine,
pMine,
pBot,
pSession,
pProduct,
@@ -76,7 +76,7 @@ function newFileSequence () {
try {
exchange = pExchange
market = pMarket
dataMine = pDataMine
mine = pMine
bot = pBot
session = pSession
dataset = pDataset
@@ -88,7 +88,7 @@ function newFileSequence () {
callerId = newUniqueId()
let key = dataMine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + dataset.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
let key = mine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + dataset.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
eventsServerClient.listenToEvent(key, 'Dataset Updated', undefined, callerId, onResponse, updateFiles)
function onResponse (message) {
@@ -97,7 +97,7 @@ function newFileSequence () {
/* First we will get the sequence max number */
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, undefined, undefined, 'Sequence', undefined, undefined, onSequenceFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, undefined, undefined, 'Sequence', undefined, undefined, onSequenceFileReceived)
function onSequenceFileReceived (err, file) {
try {
@@ -142,7 +142,7 @@ function newFileSequence () {
/* Now we will get the sequence of files */
for (let i = 0; i <= maxSequence; i++) {
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, undefined, undefined, i, undefined, undefined, onFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, undefined, undefined, i, undefined, undefined, onFileReceived)
function onFileReceived (err, file) {
try {
@@ -207,7 +207,7 @@ function newFileSequence () {
let currentMaxSequence = maxSequence
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, undefined, undefined, 'Sequence', undefined, undefined, onSequenceFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, undefined, undefined, 'Sequence', undefined, undefined, onSequenceFileReceived)
function onSequenceFileReceived (err, sequenceFile) {
try {
@@ -243,7 +243,7 @@ function newFileSequence () {
/* Now we will get the sequence of files, but in this case only from the currentMaxSequence and above. */
for (let i = currentMaxSequence; i <= maxSequence; i++) {
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, undefined, undefined, i, undefined, undefined, onFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, undefined, undefined, i, undefined, undefined, onFileReceived)
function onFileReceived (err, file) {
try {
+8 -8
View File
@@ -25,7 +25,7 @@ function newMarketFiles() {
let market
let exchange
let dataMine
let mine
let bot
let session
let dataset
@@ -55,7 +55,7 @@ function newMarketFiles() {
market = undefined
exchange = undefined
dataMine = undefined
mine = undefined
bot = undefined
session = undefined
dataset = undefined
@@ -70,7 +70,7 @@ function newMarketFiles() {
}
function initialize(
pDataMine,
pMine,
pBot,
pSession,
pProduct,
@@ -86,7 +86,7 @@ function newMarketFiles() {
exchange = pExchange
market = pMarket
dataMine = pDataMine
mine = pMine
bot = pBot
session = pSession
dataset = pDataset
@@ -108,7 +108,7 @@ function newMarketFiles() {
function getTimeFramesFile() {
/* First we will get the Data Range */
fileCloud.getFile(pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, undefined, true, onTimeFramesReceived)
fileCloud.getFile(pMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, undefined, true, onTimeFramesReceived)
function onTimeFramesReceived(err, pFile) {
switch (err.result) {
@@ -164,7 +164,7 @@ function newMarketFiles() {
}
filesExpected++
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, periodName, undefined, undefined, undefined, undefined, onFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, periodName, undefined, undefined, undefined, undefined, onFileReceived)
function onFileReceived(err, file) {
try {
@@ -177,7 +177,7 @@ function newMarketFiles() {
}
if (filesLoaded + filesNotLoaded === marketFilesPeriods.length) {
let key = dataMine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + dataset.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
let key = mine.config.codeName + '-' + bot.config.codeName + '-' + product.config.codeName + '-' + dataset.config.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
let callerId = key + '-' + periodName + newUniqueId()
eventsServerClient.listenToEvent(key, 'Dataset Updated', undefined, callerId, onResponse, updateFiles)
@@ -219,7 +219,7 @@ function newMarketFiles() {
if (message.event.timeFrames.includes(periodName) !== true) { continue }
}
}
fileCloud.getFile(dataMine, bot, session, product, dataset, exchange, market, periodName, undefined, undefined, undefined, undefined, onFileReceived)
fileCloud.getFile(mine, bot, session, product, dataset, exchange, market, periodName, undefined, undefined, undefined, undefined, onFileReceived)
function onFileReceived(err, file) {
try {
+3 -3
View File
@@ -17,7 +17,7 @@ function newSingleFile () {
return thisObject
function initialize (
pDataMine,
pMine,
pBot,
pSession,
pProduct,
@@ -30,7 +30,7 @@ function newSingleFile () {
callBackFunction) {
try {
if (INFO_LOG === true) { logger.write('[INFO] initialize -> Entering function.') }
if (INFO_LOG === true) { logger.write('[INFO] initialize -> key = ' + pDataMine.config.codeName + '-' + pBot.config.codeName + '-' + pProduct.config.codeName) }
if (INFO_LOG === true) { logger.write('[INFO] initialize -> key = ' + pMine.config.codeName + '-' + pBot.config.codeName + '-' + pProduct.config.codeName) }
let exchange = pExchange
@@ -39,7 +39,7 @@ function newSingleFile () {
/* Now we will get the file */
fileCloud.getFile(pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, undefined, undefined, onFileReceived)
fileCloud.getFile(pMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, undefined, undefined, undefined, undefined, undefined, onFileReceived)
function onFileReceived (err, pFile) {
try {
@@ -1 +1 @@
{"type":"Workspace","name":"Ethereum Integration Demo","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[],"id":"6affb9c6-6156-475a-acb5-2f9166c461cc","savedPayload":{"position":{"x":24981.241698334637,"y":30174.96791394966},"targetPosition":{"x":25073.94679664712,"y":30460.284868838204},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"af949a76-a6f4-4ec6-869e-f240480eea81","savedPayload":{"position":{"x":25073.94679664712,"y":30460.284868838204},"targetPosition":{"x":25166.651894959603,"y":30745.60182372675},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binance","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"4df1cb4e-b9ca-4f62-bb5f-c7e262aaa22a","savedPayload":{"position":{"x":25166.651894959603,"y":30745.60182372675},"targetPosition":{"x":25259.356993272086,"y":31030.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"testingEnvironment":{"type":"Testing Environment","name":"New Testing Environment","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binance","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binance BTC/USDT","project":"Superalgos","tradingMineTasks":[],"id":"846f54c2-1888-49ce-af20-4057c695ad2e","savedPayload":{"position":{"x":25780.76718989705,"y":30735.24762723981},"targetPosition":{"x":25744.76718989705,"y":30678.24762723981},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"ba36975c-08d6-458d-b7c0-eb4684a85b5d","savedPayload":{"position":{"x":25744.76718989705,"y":30678.24762723981},"targetPosition":{"x":25502.06209158457,"y":30854.58320292755},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binance","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"5882d8a8-345b-4188-b1c1-797e9ff805d9","savedPayload":{"position":{"x":25502.06209158457,"y":30854.58320292755},"targetPosition":{"x":25259.356993272086,"y":31030.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"productionEnvironment":{"type":"Production Environment","name":"New Production Environment","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binance","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binance BTC/USDT","project":"Superalgos","tradingMineTasks":[],"id":"ecb784f9-1f8a-4f09-9101-3e80546e99b9","savedPayload":{"position":{"x":25987.472288209534,"y":31559.925505678522},"targetPosition":{"x":25744.76718989705,"y":31383.58992999078},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"d539c0ac-aaeb-4c44-9dba-ac26df819a8d","savedPayload":{"position":{"x":25744.76718989705,"y":31383.58992999078},"targetPosition":{"x":25502.06209158457,"y":31207.254354303037},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binance","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"65a40d20-837c-4652-8356-f8054b4e1346","savedPayload":{"position":{"x":25502.06209158457,"y":31207.254354303037},"targetPosition":{"x":25259.356993272086,"y":31030.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunnLine truncated
{"type":"Workspace","name":"Ethereum Integration Demo","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[],"id":"6affb9c6-6156-475a-acb5-2f9166c461cc","savedPayload":{"position":{"x":24981.241698334637,"y":30174.96791394966},"targetPosition":{"x":25073.94679664712,"y":30460.284868838204},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"af949a76-a6f4-4ec6-869e-f240480eea81","savedPayload":{"position":{"x":25073.94679664712,"y":30460.284868838204},"targetPosition":{"x":25166.651894959603,"y":30745.60182372675},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binance","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"4df1cb4e-b9ca-4f62-bb5f-c7e262aaa22a","savedPayload":{"position":{"x":25166.651894959603,"y":30745.60182372675},"targetPosition":{"x":25259.356993272086,"y":31030.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"testingEnvironment":{"type":"Testing Environment","name":"New Testing Environment","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binance","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binance BTC/USDT","project":"Superalgos","tradingMineTasks":[],"id":"846f54c2-1888-49ce-af20-4057c695ad2e","savedPayload":{"position":{"x":25780.76718989705,"y":30735.24762723981},"targetPosition":{"x":25744.76718989705,"y":30678.24762723981},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"ba36975c-08d6-458d-b7c0-eb4684a85b5d","savedPayload":{"position":{"x":25744.76718989705,"y":30678.24762723981},"targetPosition":{"x":25502.06209158457,"y":30854.58320292755},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binance","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"5882d8a8-345b-4188-b1c1-797e9ff805d9","savedPayload":{"position":{"x":25502.06209158457,"y":30854.58320292755},"targetPosition":{"x":25259.356993272086,"y":31030.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"productionEnvironment":{"type":"Production Environment","name":"New Production Environment","project":"Superalgos","exchangeTradingTasks":[{"type":"Exchange Trading Tasks","name":"Binance","project":"Superalgos","marketTradingTasks":[{"type":"Market Trading Tasks","name":"Binance BTC/USDT","project":"Superalgos","tradingMineTasks":[],"id":"ecb784f9-1f8a-4f09-9101-3e80546e99b9","savedPayload":{"position":{"x":25987.472288209534,"y":31559.925505678522},"targetPosition":{"x":25744.76718989705,"y":31383.58992999078},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Market","name":"BTC/USDT","id":"9a867bf0-a71d-445c-b99a-75b60bbdce09"}}}],"id":"d539c0ac-aaeb-4c44-9dba-ac26df819a8d","savedPayload":{"position":{"x":25744.76718989705,"y":31383.58992999078},"targetPosition":{"x":25502.06209158457,"y":31207.254354303037},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Crypto Exchange","name":"Binance","id":"61ef0b8d-de6e-4e76-bdd5-996836760a4b"}}}],"id":"65a40d20-837c-4652-8356-f8054b4e1346","savedPayload":{"position":{"x":25502.06209158457,"y":31207.254354303037},"targetPosition":{"x":25259.356993272086,"y":31030.918778615294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunnLine truncated
@@ -19,9 +19,10 @@ function newSuperalgosActionSwitch() {
let functionLibraryDependenciesFilter = newDependenciesFilter()
let functionLibraryNodePath = newNodePath()
let functionLibraryTaskFunctions = newTaskFunctions()
let functionLibrarySessionFunctions = newSessionFunctions()
let functionLibraryTradingSessionFunctions = newTradingSessionFunctions()
let functionLibraryLearningSessionFunctions = newLearningSessionFunctions()
let functionLibraryCryptoEcosystemFunctions = newCryptoEcosystemFunctions()
let functionLibraryDataMineFunctions = newDataMineFunctions()
let functionLibraryMineFunctions = newMineFunctions()
let functionLibraryDataStorageFunctions = newDataStorageFunctions()
let functionLibraryChartingSpaceFunctions = newChartingSpaceFunctions()
let functionLibraryPluginsFunctions = newPluginsFunctions()
@@ -42,9 +43,10 @@ function newSuperalgosActionSwitch() {
functionLibraryDependenciesFilter = undefined
functionLibraryNodePath = undefined
functionLibraryTaskFunctions = undefined
functionLibrarySessionFunctions = undefined
functionLibraryTradingSessionFunctions = undefined
functionLibraryLearningSessionFunctions = undefined
functionLibraryCryptoEcosystemFunctions = undefined
functionLibraryDataMineFunctions = undefined
functionLibraryMineFunctions = undefined
functionLibraryDataStorageFunctions = undefined
functionLibraryChartingSpaceFunctions = undefined
functionLibraryPluginsFunctions = undefined
@@ -84,8 +86,12 @@ function newSuperalgosActionSwitch() {
functionLibraryUiObjectsFromNodes.syncronizeTasksFoundAtWorkspaceWithBackEnd(functionLibraryTaskFunctions)
}
break
case 'Syncronize Sessions': {
functionLibraryUiObjectsFromNodes.syncronizeSessionsFoundAtWorkspaceWithBackEnd(functionLibrarySessionFunctions)
case 'Syncronize Trading Sessions': {
functionLibraryUiObjectsFromNodes.syncronizeTradingSessionsFoundAtWorkspaceWithBackEnd(functionLibraryTradingSessionFunctions)
}
break
case 'Syncronize Learning Sessions': {
functionLibraryUiObjectsFromNodes.syncronizeLearningSessionsFoundAtWorkspaceWithBackEnd(functionLibraryLearningSessionFunctions)
}
break
case 'Play Tutorials': {
@@ -124,7 +130,7 @@ function newSuperalgosActionSwitch() {
break
case 'Copy Node Type':
{
let value = action.node.type
let value = action.node.type
UI.projects.superalgos.utilities.clipboard.copyTextToClipboard(value)
@@ -251,6 +257,16 @@ function newSuperalgosActionSwitch() {
functionLibraryTaskFunctions.stopAllExchangeTradingTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Run All Exchange Learning Tasks':
{
functionLibraryTaskFunctions.runAllExchangeLearningTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Stop All Exchange Learning Tasks':
{
functionLibraryTaskFunctions.stopAllExchangeLearningTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Run All Market Data Tasks':
{
functionLibraryTaskFunctions.runAllMarketDataTasks(action.node, functionLibraryProtocolNode)
@@ -271,6 +287,16 @@ function newSuperalgosActionSwitch() {
functionLibraryTaskFunctions.stopAllMarketTradingTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Run All Market Learning Tasks':
{
functionLibraryTaskFunctions.runAllMarketLearningTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Stop All Market Learning Tasks':
{
functionLibraryTaskFunctions.stopAllMarketLearningTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Run All Data Mine Tasks':
{
functionLibraryTaskFunctions.runAllDataMineTasks(action.node, functionLibraryProtocolNode)
@@ -291,6 +317,16 @@ function newSuperalgosActionSwitch() {
functionLibraryTaskFunctions.stopAllTradingMineTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Run All Learning Mine Tasks':
{
functionLibraryTaskFunctions.runAllLearningMineTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Stop All Learning Mine Tasks':
{
functionLibraryTaskFunctions.stopAllLearningMineTasks(action.node, functionLibraryProtocolNode)
}
break
case 'Add Missing Exchange Data Tasks':
{
functionLibraryTaskFunctions.addMissingExchangeDataTasks(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
@@ -321,6 +357,21 @@ function newSuperalgosActionSwitch() {
functionLibraryTaskFunctions.addMissingTradingMineTasks(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add Missing Exchange Learning Tasks':
{
functionLibraryTaskFunctions.addMissingExchangeLearningTasks(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add Missing Market Learning Tasks':
{
functionLibraryTaskFunctions.addMissingMarketLearningTasks(action.node, functionLibraryUiObjectsFromNodes)
}
break
case 'Add Missing Learning Mine Tasks':
{
functionLibraryTaskFunctions.addMissingLearningMineTasks(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add All Tasks':
{
functionLibraryTaskFunctions.addAllTasks(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
@@ -353,7 +404,7 @@ function newSuperalgosActionSwitch() {
break
case 'Add All Output Datasets':
{
functionLibraryDataMineFunctions.addAllOutputDatasets(action.node, functionLibraryUiObjectsFromNodes)
functionLibraryMineFunctions.addAllOutputDatasets(action.node, functionLibraryUiObjectsFromNodes)
}
break
case 'Add All Data Products':
@@ -366,14 +417,24 @@ function newSuperalgosActionSwitch() {
functionLibraryDataStorageFunctions.addAllDataMineProducts(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add All Learning Mine Products':
{
functionLibraryDataStorageFunctions.addAllLearningMineProducts(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add All Trading Mine Products':
{
functionLibraryDataStorageFunctions.addAllTradingMineProducts(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add Missing Session References':
case 'Add Missing Trading Session References':
{
functionLibraryDataStorageFunctions.addMissingSessionReferences(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
functionLibraryDataStorageFunctions.addMissingTradingSessionReferences(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add Missing Learning Session References':
{
functionLibraryDataStorageFunctions.addMissingLearningSessionReferences(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add Missing Market Data Products':
@@ -398,12 +459,12 @@ function newSuperalgosActionSwitch() {
break
case 'Add All Data Dependencies':
{
functionLibraryDataMineFunctions.addAllDataDependencies(action.node, functionLibraryUiObjectsFromNodes)
functionLibraryMineFunctions.addAllDataDependencies(action.node, functionLibraryUiObjectsFromNodes)
}
break
case 'Add All Data Mine Dependencies':
{
functionLibraryDataMineFunctions.addAllDataMineDataDependencies(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
functionLibraryMineFunctions.addAllDataMineDataDependencies(action.node, action.rootNodes, functionLibraryUiObjectsFromNodes)
}
break
case 'Add All Mine Layers':
@@ -461,19 +522,34 @@ function newSuperalgosActionSwitch() {
functionLibraryWebhookFunctions.sendTestMessage(action.node, action.callBackFunction)
}
break
case 'Run Session':
case 'Run Trading Session':
{
functionLibrarySessionFunctions.runSession(action.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, false, action.callBackFunction)
functionLibraryTradingSessionFunctions.runSession(action.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, false, action.callBackFunction)
}
break
case 'Resume Session':
case 'Resume Trading Session':
{
functionLibrarySessionFunctions.runSession(action.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, true, action.callBackFunction)
functionLibraryTradingSessionFunctions.runSession(action.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, true, action.callBackFunction)
}
break
case 'Stop Session':
case 'Stop Trading Session':
{
functionLibrarySessionFunctions.stopSession(action.node, functionLibraryProtocolNode, action.callBackFunction)
functionLibraryTradingSessionFunctions.stopSession(action.node, functionLibraryProtocolNode, action.callBackFunction)
}
break
case 'Run Learning Session':
{
functionLibraryLearningSessionFunctions.runSession(action.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, false, action.callBackFunction)
}
break
case 'Resume Learning Session':
{
functionLibraryLearningSessionFunctions.runSession(action.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, true, action.callBackFunction)
}
break
case 'Stop Learning Session':
{
functionLibraryLearningSessionFunctions.stopSession(action.node, functionLibraryProtocolNode, action.callBackFunction)
}
break
case 'Run Super Action':
@@ -27,8 +27,8 @@ function newChartingSpaceFunctions() {
we find there inside the layers manager. We will end up having at the end
all layers referencing the data products inside the referenced branch.
*/
let dataMine = node.payload.referenceParent
scanBotArray(dataMine.botProducts)
let mine = node.payload.referenceParent
scanBotArray(mine.botProducts)
function scanBotArray(botArray) {
for (let i = 0; i < botArray.length; i++) {
@@ -87,11 +87,13 @@ function newChartingSpaceFunctions() {
let fordwardTestingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(networkNode, 'Forward Testing Session')
let paperTradingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(networkNode, 'Paper Trading Session')
let liveTradingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(networkNode, 'Live Trading Session')
let learningSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(networkNode, 'Learning Session')
scanSessionArray(backtestingSessionsArray)
scanSessionArray(fordwardTestingSessionsArray)
scanSessionArray(paperTradingSessionsArray)
scanSessionArray(liveTradingSessionsArray)
scanSessionArray(learningSessionsArray)
function scanSessionArray(sessionsArray) {
for (let i = 0; i < sessionsArray.length; i++) {
@@ -180,7 +182,7 @@ function newChartingSpaceFunctions() {
}
}
/*
We need to create a Timeline Chart for each Data Mine Indicators.
We need to create a Timeline Chart for each Data Mine Products.
*/
mineProducts = UI.projects.superalgos.utilities.branches.nodeBranchToArray(networkNode, 'Data Mine Products')
for (let j = 0; j < mineProducts.length; j++) {
@@ -199,7 +201,38 @@ function newChartingSpaceFunctions() {
sets its own name, which we are going to reuse here.
*/
mineProduct.payload.uiObject.invisiblePhysics()
timelineChart.name = mineProduct.name
timelineChart.name = mineProduct.name + ' Data'
timelineChart.layerManager.payload.referenceParent = mineProduct
timelineChart.payload.floatingObject.collapseToggle()
timelineChart.layerManager.payload.floatingObject.collapseToggle()
timelineChart.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
timelineChart.layerManager.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let menu = timelineChart.layerManager.payload.uiObject.menu
menu.internalClick('Add All Mine Layers')
menu.internalClick('Add All Mine Layers')
}
/*
We need to create a Timeline Chart for each Learning Mine Products.
*/
mineProducts = UI.projects.superalgos.utilities.branches.nodeBranchToArray(networkNode, 'Learning Mine Products')
for (let j = 0; j < mineProducts.length; j++) {
let mineProduct = mineProducts[j]
/*
We need to filter out the ones that do not belong to the market where
the session is running at.
*/
if (mineProduct.payload.parentNode.payload.parentNode.payload.referenceParent === undefined) { continue }
if (mineProduct.payload.parentNode.payload.parentNode.payload.referenceParent.id !== market.id) { continue }
let timelineChart = functionLibraryUiObjectsFromNodes.addUIObject(timeMachine, 'Timeline Chart')
/*
The Mine Product Node might be collapesd and since its creation it never
received the physics call, so we will do the call so that it properly
sets its own name, which we are going to reuse here.
*/
mineProduct.payload.uiObject.invisiblePhysics()
timelineChart.name = mineProduct.name + ' Learning'
timelineChart.layerManager.payload.referenceParent = mineProduct
timelineChart.payload.floatingObject.collapseToggle()
timelineChart.layerManager.payload.floatingObject.collapseToggle()
@@ -251,103 +251,185 @@ function newCryptoEcosystemFunctions() {
}
function installInNetworkNode(networkNode) {
/*
Here we complete the missing stuff at Data Mining
*/
let dataMining = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Data Mining', node, true)
if (dataMining === undefined) {
node.payload.uiObject.setErrorMessage('Data Mining node not found at Network Node ' + networkNode.name)
return
}
let exchangeDataTasks = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(dataMining, 'Exchange Data Tasks', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeDataTasks.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketDataTask = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeDataTasks, 'Market Data Tasks', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
let tradingSessionsCreatedArray = []
let learningSessionsCreatedArray = []
UI.projects.superalgos.utilities.menu.menuClick(marketDataTask, 'Add Missing Data Mine Tasks', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(marketDataTask.dataMineTasks, 'Add All Tasks', true)
installDataMiningTasks()
installLearningMiningTasks()
isntallTradingMiningTasks()
let sessionsCreatedArray = []
/*
Next we complete the missing stuff at Testing Environment
*/
installEnvironment('Testing Environment')
/*
Next we complete the missing stuff at Production Environment
*/
installEnvironment('Production Environment')
installDataMinesData()
installLearningMinesData()
installTradingMineData()
function installEnvironment(environment) {
function installDataMiningTasks() {
/*
Now we install the environmnet at the current Network Node
Here we complete the missing stuff at Data Mining
*/
let environmentFound = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, environment, node, true)
if (environmentFound === undefined) {
node.payload.uiObject.setErrorMessage(environment + ' node not found at Network Node ' + networkNode.name)
let dataMining = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Data Mining', node, true)
if (dataMining === undefined) {
node.payload.uiObject.setErrorMessage('Data Mining node not found at Network Node ' + networkNode.name)
return
}
let exchangeTradingTasks = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(environmentFound, 'Exchange Trading Tasks', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeTradingTasks.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketTradingTask = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeTradingTasks, 'Market Trading Tasks', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
let exchangeDataTasks = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(dataMining, 'Exchange Data Tasks', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeDataTasks.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketDataTask = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeDataTasks, 'Market Data Tasks', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
UI.projects.superalgos.utilities.menu.menuClick(marketTradingTask, 'Add Missing Trading Mine Tasks', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(marketTradingTask.tradingMineTasks, 'Add All Tasks', true)
/* This will be needed at the charging space, for creating Dashboards */
let backtestingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(marketTradingTask, 'Backtesting Session')
let liveTradingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(marketTradingTask, 'Live Trading Session')
let allSessionsArray = backtestingSessionsArray.concat(liveTradingSessionsArray)
sessionsCreatedArray = sessionsCreatedArray.concat(allSessionsArray)
dashboardsArray.push({ environmentNode: environmentFound, networkNode: networkNode, sessionsArray: allSessionsArray })
}
/*
Here we complete the missing stuff at Data Mines Data
*/
let dataMinesData = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Data Mines Data', node, true)
if (dataMinesData === undefined) {
node.payload.uiObject.setErrorMessage('Data Mines Data node not found at Network Node ' + networkNode.name)
return
UI.projects.superalgos.utilities.menu.menuClick(marketDataTask, 'Add Missing Data Mine Tasks', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(marketDataTask.dataMineTasks, 'Add All Tasks', true)
}
let exchangeDataProducts = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(dataMinesData, 'Exchange Data Products', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeDataProducts.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketDataProducts = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeDataProducts, 'Market Data Products', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
marketDataProducts.payload.floatingObject.collapseToggle()
function installLearningMiningTasks() {
/*
Here we complete the missing stuff at Learning Mining
*/
let learningMining = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Learning Mining', node, true)
if (learningMining === undefined) {
node.payload.uiObject.setErrorMessage('Learning Mining node not found at Network Node ' + networkNode.name)
return
}
UI.projects.superalgos.utilities.menu.menuClick(marketDataProducts, 'Add All Data Mine Products', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(marketDataProducts.dataMineProducts, 'Add All Data Products', true)
/*
Finally we complete the missing stuff at Trading Mines Data
*/
let tradingMinesData = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Trading Mines Data', node, true)
if (tradingMinesData === undefined) {
node.payload.uiObject.setErrorMessage('Trading Mines Data node not found at Network Node ' + networkNode.name)
return
let exchangeLearningTasks = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(learningMining, 'Exchange Learning Tasks', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeLearningTasks.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketLearningTask = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeLearningTasks, 'Market Learning Tasks', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
UI.projects.superalgos.utilities.menu.menuClick(marketLearningTask, 'Add Missing Learning Mine Tasks', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(marketLearningTask.learningMineTasks, 'Add All Tasks', true)
/* This will be needed at the charting space, for creating Dashboards */
let learningSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(marketLearningTask, 'Learning Session')
learningSessionsCreatedArray = learningSessionsCreatedArray.concat(learningSessionsArray)
}
let exchangeTradingProducts = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(tradingMinesData, 'Exchange Trading Products', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeTradingProducts.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketTradingProducts = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeTradingProducts, 'Market Trading Products', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
marketTradingProducts.payload.floatingObject.collapseToggle()
/*
Create the new session references.
*/
for (let i = 0; i < sessionsCreatedArray.length; i++) {
let session = sessionsCreatedArray[i]
if (UI.projects.superalgos.utilities.children.isMissingChildren(marketTradingProducts, session, true) === true) {
functionLibraryDataStorageFunctions.createSessionReference(marketTradingProducts, session, functionLibraryUiObjectsFromNodes)
function isntallTradingMiningTasks() {
/*
Next we complete the missing stuff at Testing Environment
*/
installEnvironment('Testing Environment')
/*
Next we complete the missing stuff at Production Environment
*/
installEnvironment('Production Environment')
function installEnvironment(environment) {
/*
Now we install the environmnet at the current Network Node
*/
let environmentFound = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, environment, node, true)
if (environmentFound === undefined) {
node.payload.uiObject.setErrorMessage(environment + ' node not found at Network Node ' + networkNode.name)
return
}
let exchangeTradingTasks = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(environmentFound, 'Exchange Trading Tasks', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeTradingTasks.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketTradingTask = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeTradingTasks, 'Market Trading Tasks', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
UI.projects.superalgos.utilities.menu.menuClick(marketTradingTask, 'Add Missing Trading Mine Tasks', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(marketTradingTask.tradingMineTasks, 'Add All Tasks', true)
/* This will be needed at the charting space, for creating Dashboards */
let backtestingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(marketTradingTask, 'Backtesting Session')
let liveTradingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(marketTradingTask, 'Live Trading Session')
let paperTradingSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(marketTradingTask, 'Paper Trading Session')
let forwardSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(marketTradingTask, 'Forward Testing Session')
let allSessionsArray = backtestingSessionsArray
.concat(liveTradingSessionsArray)
.concat(paperTradingSessionsArray)
.concat(forwardSessionsArray)
tradingSessionsCreatedArray = tradingSessionsCreatedArray.concat(allSessionsArray)
dashboardsArray.push({ environmentNode: environmentFound, networkNode: networkNode, sessionsArray: allSessionsArray })
}
}
/*
Create everything inside the session references.
*/
for (let j = 0; j < marketTradingProducts.sessionReferences.length; j++) {
let sessionReference = marketTradingProducts.sessionReferences[j]
UI.projects.superalgos.utilities.menu.menuClick(sessionReference, 'Add All Trading Mine Products', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(sessionReference.tradingMineProducts, 'Add All Data Products', true)
sessionReference.payload.floatingObject.collapseToggle()
function installDataMinesData() {
/*
Here we complete the missing stuff at Data Mines Data
*/
let dataMinesData = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Data Mines Data', node, true)
if (dataMinesData === undefined) {
node.payload.uiObject.setErrorMessage('Data Mines Data node not found at Network Node ' + networkNode.name)
return
}
let exchangeDataProducts = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(dataMinesData, 'Exchange Data Products', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeDataProducts.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketDataProducts = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeDataProducts, 'Market Data Products', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
marketDataProducts.payload.floatingObject.collapseToggle()
UI.projects.superalgos.utilities.menu.menuClick(marketDataProducts, 'Add All Data Mine Products', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(marketDataProducts.dataMineProducts, 'Add All Data Products', true)
}
function installLearningMinesData() {
/*
Here we complete the missing stuff at Learning Mines Data
*/
let learningMinesData = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Learning Mines Data', node, true)
if (learningMinesData === undefined) {
node.payload.uiObject.setErrorMessage('Learning Mines Data node not found at Network Node ' + networkNode.name)
return
}
let exchangeLearningProducts = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(learningMinesData, 'Exchange Learning Products', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeLearningProducts.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketLearningProducts = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeLearningProducts, 'Market Learning Products', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
marketLearningProducts.payload.floatingObject.collapseToggle()
/*
Create the new session references.
*/
for (let i = 0; i < learningSessionsCreatedArray.length; i++) {
let session = learningSessionsCreatedArray[i]
if (UI.projects.superalgos.utilities.children.isMissingChildren(marketLearningProducts, session, true) === true) {
functionLibraryDataStorageFunctions.createSessionReference(marketLearningProducts, session, 'Learning Session Reference', functionLibraryUiObjectsFromNodes)
}
}
/*
Create everything inside the session references.
*/
for (let j = 0; j < marketLearningProducts.learningSessionReferences.length; j++) {
let sessionReference = marketLearningProducts.learningSessionReferences[j]
UI.projects.superalgos.utilities.menu.menuClick(sessionReference, 'Add All Learning Mine Products', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(sessionReference.learningMineProducts, 'Add All Data Products', true)
sessionReference.payload.floatingObject.collapseToggle()
}
}
function installTradingMineData() {
/*
Finally we complete the missing stuff at Trading Mines Data
*/
let tradingMinesData = UI.projects.superalgos.utilities.branches.findInBranch(networkNode, 'Trading Mines Data', node, true)
if (tradingMinesData === undefined) {
node.payload.uiObject.setErrorMessage('Trading Mines Data node not found at Network Node ' + networkNode.name)
return
}
let exchangeTradingProducts = UI.projects.superalgos.utilities.children.findOrCreateChildWithReference(tradingMinesData, 'Exchange Trading Products', cryptoExchange, functionLibraryUiObjectsFromNodes)
exchangeTradingProducts.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
let marketTradingProducts = UI.projects.superalgos.utilities.children.findAndRecreateChildWithReference(exchangeTradingProducts, 'Market Trading Products', market, rootNodes, functionLibraryUiObjectsFromNodes, functionLibraryNodeDeleter)
marketTradingProducts.payload.floatingObject.collapseToggle()
/*
Create the new session references.
*/
for (let i = 0; i < tradingSessionsCreatedArray.length; i++) {
let session = tradingSessionsCreatedArray[i]
if (UI.projects.superalgos.utilities.children.isMissingChildren(marketTradingProducts, session, true) === true) {
functionLibraryDataStorageFunctions.createSessionReference(marketTradingProducts, session, 'Trading Session Reference', functionLibraryUiObjectsFromNodes)
}
}
/*
Create everything inside the session references.
*/
for (let j = 0; j < marketTradingProducts.tradingSessionReferences.length; j++) {
let sessionReference = marketTradingProducts.tradingSessionReferences[j]
UI.projects.superalgos.utilities.menu.menuClick(sessionReference, 'Add All Trading Mine Products', true)
UI.projects.superalgos.utilities.menu.menuClickOfNodeArray(sessionReference.tradingMineProducts, 'Add All Data Products', true)
sessionReference.payload.floatingObject.collapseToggle()
}
}
}
}
@@ -450,13 +532,17 @@ function newCryptoEcosystemFunctions() {
let marketDataTasksArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(network, 'Market Data Tasks')
let marketTradingTasksArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(network, 'Market Trading Tasks')
let marketLearningTasksArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(network, 'Market Learning Tasks')
let marketDataProductsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(network, 'Market Data Products')
let marketTradingProductsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(network, 'Market Trading Products')
let marketLearningProductsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(network, 'Market Learning Products')
uninstalMarketArray(marketDataTasksArray)
uninstalMarketArray(marketTradingTasksArray)
uninstalMarketArray(marketLearningTasksArray)
uninstalMarketArray(marketDataProductsArray)
uninstalMarketArray(marketTradingProductsArray)
uninstalMarketArray(marketLearningProductsArray)
function uninstalMarketArray(marketArray) {
for (let i = 0; i < marketArray.length; i++) {
@@ -3,7 +3,9 @@ function newDataStorageFunctions() {
addAllDataProducts: addAllDataProducts,
addAllDataMineProducts: addAllDataMineProducts,
addAllTradingMineProducts: addAllTradingMineProducts,
addMissingSessionReferences: addMissingSessionReferences,
addAllLearningMineProducts: addAllLearningMineProducts,
addMissingTradingSessionReferences: addMissingTradingSessionReferences,
addMissingLearningSessionReferences: addMissingLearningSessionReferences,
addMissingMarketDataProducts: addMissingMarketDataProducts,
addMissingMarketTradingProducts: addMissingMarketTradingProducts,
addMissingExchangeTradingProducts: addMissingExchangeTradingProducts,
@@ -37,6 +39,7 @@ function newDataStorageFunctions() {
scanBotArray(mine.sensorBots)
scanBotArray(mine.indicatorBots)
scanBotArray(mine.tradingBots)
scanBotArray(mine.learningBots)
function scanBotArray(botArray) {
if (botArray === undefined) { return }
@@ -84,7 +87,18 @@ function newDataStorageFunctions() {
}
}
function addMissingSessionReferences(node, rootNodes, functionLibraryUiObjectsFromNodes) {
function addAllLearningMineProducts(node, rootNodes, functionLibraryUiObjectsFromNodes) {
for (let i = 0; i < rootNodes.length; i++) {
let rootNode = rootNodes[i]
if (rootNode.type === 'Learning Mine') {
let learningMineProducts = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Learning Mine Products')
learningMineProducts.payload.referenceParent = rootNode
}
}
}
function addMissingTradingSessionReferences(node, rootNodes, functionLibraryUiObjectsFromNodes) {
let networkNode = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(node, 'Network Node', undefined, true, false, true, false)
if (networkNode === undefined) { return }
@@ -105,14 +119,35 @@ function newDataStorageFunctions() {
let marketTradingTasks = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(session, 'Market Trading Tasks', undefined, true, false, true, false)
if (node.payload.referenceParent.id !== marketTradingTasks.payload.referenceParent.id) { continue }
if (UI.projects.superalgos.utilities.children.isMissingChildren(node, session, true) === true) {
createSessionReference(node, session, functionLibraryUiObjectsFromNodes)
createSessionReference(node, session, 'Trading Session Reference', functionLibraryUiObjectsFromNodes)
}
}
}
}
function createSessionReference(node, session, functionLibraryUiObjectsFromNodes) {
let sessionReference = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Session Reference')
function addMissingLearningSessionReferences(node, rootNodes, functionLibraryUiObjectsFromNodes) {
let networkNode = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(node, 'Network Node', undefined, true, false, true, false)
if (networkNode === undefined) { return }
let learningSessionsArray = UI.projects.superalgos.utilities.branches.nodeBranchToArray(networkNode, 'Learning Session')
addMissingSession(learningSessionsArray)
function addMissingSession(sessionsArray) {
for (let i = 0; i < sessionsArray.length; i++) {
let session = sessionsArray[i]
/* We will filter out all the sessions that does not belong to the market we are in */
let marketLearningTasks = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(session, 'Market Learning Tasks', undefined, true, false, true, false)
if (node.payload.referenceParent.id !== marketLearningTasks.payload.referenceParent.id) { continue }
if (UI.projects.superalgos.utilities.children.isMissingChildren(node, session, true) === true) {
createSessionReference(node, session, 'Learning Session Reference', functionLibraryUiObjectsFromNodes)
}
}
}
}
function createSessionReference(node, session, nodeType, functionLibraryUiObjectsFromNodes) {
let sessionReference = functionLibraryUiObjectsFromNodes.addUIObject(node, nodeType)
sessionReference.payload.referenceParent = session
}
@@ -0,0 +1,235 @@
function newLearningSessionFunctions() {
thisObject = {
syncronizeSessionWithBackEnd: syncronizeSessionWithBackEnd,
runSession: runSession,
stopSession: stopSession
}
return thisObject
function syncronizeSessionWithBackEnd(node) {
let networkNode = validations(node)
if (networkNode === undefined) {
/* Nodes that do not belong to a network can not get ready. */
return
}
let eventsServerClient = UI.projects.superalgos.spaces.designSpace.workspace.eventsServerClients.get(networkNode.id)
/* First we setup everything so as to listen to the response from the Task Server */
let eventSubscriptionIdOnStatus
let key = node.name + '-' + node.type + '-' + node.id
eventsServerClient.listenToEvent(key, 'Status Response', undefined, node.id, onResponse, onStatus)
function onResponse(message) {
eventSubscriptionIdOnStatus = message.eventSubscriptionId
}
function onStatus(message) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnStatus, node.id)
if (message.event.status === 'Learning Session Runnning' ) {
node.payload.uiObject.menu.internalClick('Run Learning Session')
}
}
/* Second we ask the Task Server if this Session is Running. */
eventsServerClient.raiseEvent(key, 'Learning Session Status')
}
function runSession(node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, resume, callBackFunction) {
let networkNode = validations(node)
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)
node.payload.uiObject.run(eventsServerClient, callBackFunction)
let key = node.name + '-' + node.type + '-' + node.id
let lightingPath = '' +
'Trading System->' +
'Dynamic Indicators->Indicator Function->Formula->' +
'Trading Strategy->' +
'Trigger Stage->Trigger On Event->Trigger Off Event->Take Position Event->' +
'Announcement->Announcement Formula->' +
'Open Stage->' +
'Manage Stage->' +
'Managed Stop Loss->Managed Take Profit->' +
'Phase->Formula->Next Phase Event->Move To Phase Event->Phase->' +
'Situation->Condition->Javascript Code->' +
'Close Stage->' +
'Initial Targets->Target Size In Base Asset->Target Size In Quoted Asset->Target Rate->Formula->' +
'Announcement->Announcement Formula->' +
'Open Execution->Close Execution->' +
'Execution Algorithm->Market Buy Order->Market Sell Order->Limit Buy Order->Limit Sell Order->' +
'Order Rate->Formula->' +
'Create Order Event->Cancel Order Event->' +
'Size In Base Asset->Size In Quoted Asset->Position Rate->Formula->' +
'Situation->Condition->Javascript Code->' +
'Market Order->Limit Order->' +
'Simulated Exchange Events->Simulated Partial Fill->Simulated Actual Rate->Simulated Fees Paid->Formula->'
let tradingSystem = functionLibraryProtocolNode.getProtocolNode(node.tradingSystemReference.payload.referenceParent, false, true, true, false, false, lightingPath)
lightingPath = '' +
'Trading Engine->' +
'Dynamic Indicators->Indicator Function->' +
'Current->Last->Previous->' +
'Episode->' +
'Episode Base Asset->Episode Quoted Asset->Episode Counters->Episode Statistics->' +
'Strategies->Positions->Orders->Hits->Fails->' +
'Profit Loss->Hit Ratio->Hit Fail->Days->ROI->Annualized Rate Of Return->User Defined Statistic->' +
'Candle->Cycle->' +
'Begin->End->Last Begin->Last End->Open->Close->Min->Max->Index->' +
'Distance To Event->' +
'Head Of The Market->Process Date->' +
'Trigger On->Trigger Off->Take Position->Close Position->Next Phase->Move To Phase->Create Order->Cancel Order->Close Order->' +
'Strategy->' +
'Strategy Counters->' +
'Position->' +
'Entry Target Rate->Exit Target Rate->' +
'Stop Loss->Stop Loss Phase->Stop Loss Position->Begin->End->Initial Value->Final Value->' +
'Take Profit->Take Profit Phase->Take Profit Position->Begin->End->Initial Value->Final Value->' +
'Position Counters->' +
'Position Statistics->Days->User Defined Statistic->' +
'Position Base Asset->Position Quoted Asset->Entry Target Size->Exit Target Size->' +
'Profit Loss->ROI->Hit Fail->' +
'Exchange Orders->Market Buy Orders->Market Sell Orders->Limit Buy Orders->Limit Sell Orders->' +
'Market Order->Limit Order->' +
'Exchange Id->Rate->Order Name->Algorithm Name->Lock->' +
'Order Counters->' +
'Order Base Asset->Order Quoted Asset->' +
'Actual Size->Size->Size Filled->Amount Received->Fees Paid->Fees To Be Paid->' +
'Order Statistics->Percentage Filled->Actual Rate->Days->User Defined Statistic->' +
'Strategy Trigger Stage->Strategy Open Stage->Strategy Manage Stage->Strategy Close Stage->' +
'Begin->End->Exit Type->Status->Begin Rate->End Rate->Stage Base Asset->Stage Quoted Asset->Size Placed->Target Size->Size Filled->Fees Paid->Stage Defined In->' +
'Serial Number->Identifier->Begin->End->Begin Rate->End Rate->Strategy Name->Status->Exit Type->' +
'Balance->Begin Balance->End Balance->' +
'Index->Situation Name->Formula->Periods->'
let tradingEngine = functionLibraryProtocolNode.getProtocolNode(node.tradingEngineReference.payload.referenceParent, false, true, true, false, false, lightingPath)
lightingPath = '' +
'Learning Session->' +
'Parameters->' +
'Session Base Asset->Session Quoted Asset->Time Range->Time Frame->Slippage->Fee Structure->Snapshots->Heartbeats->User Defined Parameters->' +
'Exchange Account Asset->Asset->' +
'Social Bots->Telegram Bot->'
let session = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
let dependencyFilter = functionLibraryDependenciesFilter.createFilter(node.tradingSystemReference.payload.referenceParent)
/* Raise event to run the session */
let event = {
session: JSON.stringify(session),
tradingSystem: JSON.stringify(tradingSystem),
tradingEngine: JSON.stringify(tradingEngine),
dependencyFilter: JSON.stringify(dependencyFilter),
resume: resume
}
if (resume !== true) {
eventsServerClient.raiseEvent(key, 'Run Learning Session', event)
} else {
eventsServerClient.raiseEvent(key, 'Resume Learning Session', event)
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
}
function stopSession(node, functionLibraryProtocolNode, callBackFunction) {
let networkNode = validations(node)
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
eventsServerClient.raiseEvent(key, 'Stop Learning Session')
node.payload.uiObject.stop(callBackFunction)
}
function validations(node) {
if (node.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be able to run.')
return
}
if (node.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside a Process Instance node.')
return
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside a Task.')
return
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside a Task Manager.')
return
}
let taskManager = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode
if (taskManager.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside Mine Tasks.')
return
}
if (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) {
node.payload.uiObject.setErrorMessage('Session needs to be inside Exchange Tasks.')
return
}
if (taskManager.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside a Testing or Production Environment.')
return
}
if (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 = taskManager.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode
if (node.tradingSystemReference === undefined) {
node.payload.uiObject.setErrorMessage('Session needs a child Trading System Reference.')
return
}
if (node.tradingEngineReference === undefined) {
node.payload.uiObject.setErrorMessage('Session needs a child Trading Engine Reference.')
return
}
if (node.tradingSystemReference.payload.referenceParent === undefined) {
node.payload.uiObject.setErrorMessage('Trading System Reference needs to reference a Trading System.')
return
}
if (node.tradingEngineReference.payload.referenceParent === undefined) {
node.payload.uiObject.setErrorMessage('Trading Engine Reference needs to reference a Trading Engine.')
return
}
return networkNode
}
}
@@ -1,4 +1,4 @@
function newDataMineFunctions() {
function newMineFunctions() {
thisObject = {
addAllOutputDatasets: addAllOutputDatasets,
addAllDataDependencies: addAllDataDependencies,
@@ -68,6 +68,7 @@ function newDataMineFunctions() {
scanBotArray(dataMine.sensorBots)
scanBotArray(dataMine.indicatorBots)
scanBotArray(dataMine.tradingBots)
scanBotArray(dataMine.learningBots)
function scanBotArray(botArray) {
for (let i = 0; i < botArray.length; i++) {
@@ -13,16 +13,22 @@ function newTaskFunctions() {
stopAllExchangeDataTasks: stopAllExchangeDataTasks,
runAllExchangeTradingTasks: runAllExchangeTradingTasks,
stopAllExchangeTradingTasks: stopAllExchangeTradingTasks,
runAllExchangeLearningTasks: runAllExchangeLearningTasks,
stopAllExchangeLearningTasks: stopAllExchangeLearningTasks,
runAllMarketDataTasks: runAllMarketDataTasks,
stopAllMarketDataTasks: stopAllMarketDataTasks,
runAllMarketTradingTasks: runAllMarketTradingTasks,
stopAllMarketTradingTasks: stopAllMarketTradingTasks,
runAllMarketLearningTasks: runAllMarketLearningTasks,
stopAllMarketLearningTasks: stopAllMarketLearningTasks,
runAllDataMineTasks: runAllDataMineTasks,
stopAllDataMineTasks: stopAllDataMineTasks,
runAllTradingMineTasks: runAllTradingMineTasks,
stopAllTradingMineTasks: stopAllTradingMineTasks,
runAllLearningMineTasks: runAllLearningMineTasks,
stopAllLearningMineTasks: stopAllLearningMineTasks,
addMissingExchangeDataTasks: addMissingExchangeDataTasks,
addMissingMarketDataTasks: addMissingMarketDataTasks,
@@ -30,6 +36,10 @@ function newTaskFunctions() {
addMissingExchangeTradingTasks: addMissingExchangeTradingTasks,
addMissingMarketTradingTasks: addMissingMarketTradingTasks,
addMissingTradingMineTasks: addMissingTradingMineTasks,
addMissingExchangeLearningTasks: addMissingExchangeLearningTasks,
addMissingMarketLearningTasks: addMissingMarketLearningTasks,
addMissingLearningMineTasks: addMissingLearningMineTasks,
addAllTasks: addAllTasks
}
@@ -91,16 +101,18 @@ function newTaskFunctions() {
'Sensor Bot Instance->' +
'Indicator Bot Instance->Time Frames Filter->' +
'Trading Bot Instance->' +
'Sensor Process Instance->Indicator Process Instance->Trading Process Instance->' +
'Learning Bot Instance->' +
'Sensor Process Instance->Indicator Process Instance->Trading Process Instance->Learning Process Instance->' +
'Execution Started Event->' +
'Key Reference->Exchange Account Key->' +
'Task Manager->' +
'Data Mine Tasks->Trading Mine Tasks->' +
'Market Data Tasks->Market Trading Tasks->' +
'Exchange Data Tasks->Exchange Trading Tasks->' +
'Data Mine Tasks->Trading Mine Tasks->Learning Mine Tasks->' +
'Market Data Tasks->Market Trading Tasks->Market Learning Tasks->' +
'Exchange Data Tasks->Exchange Trading Tasks->Exchange Learning Tasks->' +
'Market->Exchange Markets->Crypto Exchange->' +
'Market Base Asset->Market Quoted Asset->Asset->' +
'Backtesting Session->Live Trading Session->Paper Trading Session->Forward Testing Session->' +
'Learning Session->' +
'Process Definition->' +
'Process Output->' +
'Output Dataset Folder->Output Dataset Folder->Output Dataset Folder->Output Dataset Folder->Output Dataset Folder->' +
@@ -124,7 +136,8 @@ function newTaskFunctions() {
'Product Definition Folder->Product Definition Folder->Product Definition Folder->Product Definition Folder->Product Definition Folder->' +
'Indicator Bot->' +
'Trading Bot->' +
'Data Mine->Trading Mine->'
'Learning Bot->' +
'Data Mine->Trading Mine->Learning Mine->'
let taskDefinition = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, taskLightingPath)
@@ -134,14 +147,14 @@ function newTaskFunctions() {
'Data Mine Products->Bot Products->' +
'Data Product Folder->Data Product Folder->Data Product Folder->Data Product Folder->Data Product Folder->' +
'Data Product->Product Definition->' +
'Data Mining->Testing Environment->Production Environment->' +
'Exchange Data Tasks->Exchange Trading Tasks->Crypto Exchange->' +
'Market Data Tasks->Market Trading Tasks->Market->' +
'Data Mine Tasks->Trading Mine Tasks->' +
'Data Mining->Learning Mining->Testing Environment->Production Environment->' +
'Exchange Data Tasks->Exchange Trading Tasks->Exchange Learning Tasks->Crypto Exchange->' +
'Market Data Tasks->Market Trading Tasks->Market Learning Tasks->Market->' +
'Data Mine Tasks->Trading Mine Tasks->Learning Mine Tasks->' +
'Task Manager->Task->' +
'Indicator Bot Instance->Sensor Bot Instance->Trading Bot Instance->' +
'Indicator Process Instance->Sensor Process Instance->Trading Process Instance->' +
'Paper Trading Session->Forward Testing Session->Backtesting Session->Live Trading Session->' +
'Indicator Bot Instance->Sensor Bot Instance->Trading Bot Instance->Learning Bot Instance->' +
'Indicator Process Instance->Sensor Process Instance->Trading Process Instance->Learning Process Instance->' +
'Paper Trading Session->Forward Testing Session->Backtesting Session->Live Trading Session->Learning Session->' +
'Market->' +
'Process Definition->'
@@ -227,7 +240,7 @@ function newTaskFunctions() {
}
if (taskManager.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Task needs to be inside a Data Mining, Testing or Production Environment.')
node.payload.uiObject.setErrorMessage('Task needs to be inside a Data Mining, Learning Mining, Testing or Production Environment node.')
return
}
@@ -333,6 +346,26 @@ function newTaskFunctions() {
}
}
function runAllExchangeLearningTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.exchangeLearningTasks.length; i++) {
let node = parent.exchangeLearningTasks[i]
let menu = node.payload.uiObject.menu
menu.internalClick('Run All Market Learning Tasks')
menu.internalClick('Run All Market Learning Tasks')
}
}
function stopAllExchangeLearningTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.exchangeLearningTasks.length; i++) {
let node = parent.exchangeLearningTasks[i]
let menu = node.payload.uiObject.menu
menu.internalClick('Stop All Market Learning Tasks')
menu.internalClick('Stop All Market Learning Tasks')
}
}
function runAllMarketDataTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.marketDataTasks.length; i++) {
let node = parent.marketDataTasks[i]
@@ -363,6 +396,16 @@ function newTaskFunctions() {
}
}
function runAllMarketLearningTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.marketLearningTasks.length; i++) {
let node = parent.marketLearningTasks[i]
let menu = node.payload.uiObject.menu
menu.internalClick('Run All Learning Mine Tasks')
menu.internalClick('Run All Learning Mine Tasks')
}
}
function stopAllMarketTradingTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.marketTradingTasks.length; i++) {
let node = parent.marketTradingTasks[i]
@@ -373,6 +416,16 @@ function newTaskFunctions() {
}
}
function stopAllMarketLearningTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.marketLearningTasks.length; i++) {
let node = parent.marketLearningTasks[i]
let menu = node.payload.uiObject.menu
menu.internalClick('Stop All Learning Mine Tasks')
menu.internalClick('Stop All Learning Mine Tasks')
}
}
function runAllDataMineTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.dataMineTasks.length; i++) {
let node = parent.dataMineTasks[i]
@@ -403,6 +456,16 @@ function newTaskFunctions() {
}
}
function runAllLearningMineTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.learningMineTasks.length; i++) {
let node = parent.learningMineTasks[i]
let menu = node.payload.uiObject.menu
menu.internalClick('Run All Task Managers')
menu.internalClick('Run All Task Managers')
}
}
function stopAllTradingMineTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.tradingMineTasks.length; i++) {
let node = parent.tradingMineTasks[i]
@@ -413,6 +476,16 @@ function newTaskFunctions() {
}
}
function stopAllLearningMineTasks(parent, functionLibraryProtocolNode) {
for (let i = 0; i < parent.learningMineTasks.length; i++) {
let node = parent.learningMineTasks[i]
let menu = node.payload.uiObject.menu
menu.internalClick('Stop All Task Managers')
menu.internalClick('Stop All Task Managers')
}
}
function addMissingExchangeDataTasks(node, rootNodes, functionLibraryUiObjectsFromNodes) {
addMissingExchangeTasks(node, rootNodes, 'Exchange Data Tasks', functionLibraryUiObjectsFromNodes)
}
@@ -421,6 +494,10 @@ function newTaskFunctions() {
addMissingExchangeTasks(node, rootNodes, 'Exchange Trading Tasks', functionLibraryUiObjectsFromNodes)
}
function addMissingExchangeLearningTasks(node, rootNodes, functionLibraryUiObjectsFromNodes) {
addMissingExchangeTasks(node, rootNodes, 'Exchange Learning Tasks', functionLibraryUiObjectsFromNodes)
}
function addMissingExchangeTasks(node, rootNodes, newNodeType, functionLibraryUiObjectsFromNodes) {
for (let i = 0; i < rootNodes.length; i++) {
let rootNode = rootNodes[i]
@@ -448,6 +525,10 @@ function newTaskFunctions() {
addMissingMarketTasks(node, 'Market Trading Tasks', functionLibraryUiObjectsFromNodes)
}
function addMissingMarketLearningTasks(node, functionLibraryUiObjectsFromNodes) {
addMissingMarketTasks(node, 'Market Learning Tasks', functionLibraryUiObjectsFromNodes)
}
function addMissingMarketTasks(node, newNodeType, functionLibraryUiObjectsFromNodes) {
if (node.payload === undefined) { return }
if (node.payload.referenceParent === undefined) { return }
@@ -473,15 +554,19 @@ function newTaskFunctions() {
addMissingMineTasks(node, rootNodes, 'Trading Mine', 'Trading Mine Tasks', functionLibraryUiObjectsFromNodes)
}
function addMissingLearningMineTasks(node, rootNodes, functionLibraryUiObjectsFromNodes) {
addMissingMineTasks(node, rootNodes, 'Learning Mine', 'Learning Mine Tasks', functionLibraryUiObjectsFromNodes)
}
function addMissingMineTasks(node, rootNodes, rootNodeType, newNodeType, functionLibraryUiObjectsFromNodes) {
for (let i = 0; i < rootNodes.length; i++) {
let rootNode = rootNodes[i]
if (rootNode.type === rootNodeType) {
let dataMine = rootNode
let mine = rootNode
if (UI.projects.superalgos.utilities.children.isMissingChildren(node, dataMine, true) === true) {
if (UI.projects.superalgos.utilities.children.isMissingChildren(node, mine, true) === true) {
let dataMineTasks = functionLibraryUiObjectsFromNodes.addUIObject(node, newNodeType)
dataMineTasks.payload.referenceParent = dataMine
dataMineTasks.payload.referenceParent = mine
}
}
}
@@ -500,6 +585,10 @@ function newTaskFunctions() {
addDataTasks()
break
}
case 'Learning Mine Tasks': {
addLearningTasks()
break
}
case 'Trading Mine Tasks': {
addTradingTasks()
break
@@ -510,6 +599,10 @@ function newTaskFunctions() {
addTaskForTradinSystem()
}
function addLearningTasks() {
addTaskForTradinSystem()
}
function addTradingTasks() {
for (let i = 0; i < rootNodes.length; i++) {
let rootNode = rootNodes[i]
@@ -525,6 +618,7 @@ function newTaskFunctions() {
addTasksForBotArray(mine.sensorBots)
addTasksForBotArray(mine.indicatorBots)
addTasksForBotArray(mine.tradingBots)
addTasksForBotArray(mine.learningBots)
function addTasksForBotArray(botsArray) {
if (botsArray === undefined) { return }
@@ -557,6 +651,11 @@ function newTaskFunctions() {
botInstance.name = bot.name
break
}
case 'Learning Bot': {
botInstance = functionLibraryUiObjectsFromNodes.addUIObject(task, 'Learning Bot Instance')
botInstance.name = bot.name
break
}
}
for (let j = 0; j < bot.processes.length; j++) {
@@ -598,6 +697,32 @@ function newTaskFunctions() {
}
break
function addSession(sessionType) {
session = functionLibraryUiObjectsFromNodes.addUIObject(processInstance, sessionType)
session.name = task.name
let config = JSON.parse(session.config)
config.folderName = session.name.split(" ").join("-")
session.config = JSON.stringify(config)
for (let m = 0; m < rootNodes.length; m++) {
let rootNode = rootNodes[m]
if (rootNode.type === 'Trading Engine' && rootNode.isPlugin === true) {
let tradingEngine = rootNode
session.tradingEngineReference.payload.referenceParent = tradingEngine
session.tradingSystemReference.payload.referenceParent = tradingSystem
}
}
}
}
case 'Learning Bot': {
processInstance = functionLibraryUiObjectsFromNodes.addUIObject(botInstance, 'Learning Process Instance')
processInstance.payload.referenceParent = process
let session
addSession('Learning Session')
break
function addSession(sessionType) {
session = functionLibraryUiObjectsFromNodes.addUIObject(processInstance, sessionType)
session.name = task.name
@@ -1,4 +1,4 @@
function newSessionFunctions() {
function newTradingSessionFunctions() {
thisObject = {
syncronizeSessionWithBackEnd: syncronizeSessionWithBackEnd,
runSession: runSession,
@@ -27,13 +27,13 @@ function newSessionFunctions() {
function onStatus(message) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnStatus, node.id)
if (message.event.status === 'Session Runnning' ) {
node.payload.uiObject.menu.internalClick('Run Session')
if (message.event.status === 'Trading Session Runnning' ) {
node.payload.uiObject.menu.internalClick('Run Trading Session')
}
}
/* Second we ask the Task Server if this Session is Running. */
eventsServerClient.raiseEvent(key, 'Session Status')
eventsServerClient.raiseEvent(key, 'Trading Session Status')
}
function runSession(node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, resume, callBackFunction) {
@@ -134,9 +134,9 @@ function newSessionFunctions() {
}
if (resume !== true) {
eventsServerClient.raiseEvent(key, 'Run Session', event)
eventsServerClient.raiseEvent(key, 'Run Trading Session', event)
} else {
eventsServerClient.raiseEvent(key, 'Resume Session', event)
eventsServerClient.raiseEvent(key, 'Resume Trading Session', event)
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
@@ -156,7 +156,7 @@ function newSessionFunctions() {
let eventsServerClient = UI.projects.superalgos.spaces.designSpace.workspace.eventsServerClients.get(networkNode.id)
let key = node.name + '-' + node.type + '-' + node.id
eventsServerClient.raiseEvent(key, 'Stop Session')
eventsServerClient.raiseEvent(key, 'Stop Trading Session')
node.payload.uiObject.stop(callBackFunction)
}
@@ -168,7 +168,7 @@ function newSessionFunctions() {
}
if (node.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside a Trading Process Instance.')
node.payload.uiObject.setErrorMessage('Session needs to be inside a Process Instance node.')
return
}
@@ -1,7 +1,8 @@
function newUiObjectsFromNodes() {
thisObject = {
syncronizeTasksFoundAtWorkspaceWithBackEnd: syncronizeTasksFoundAtWorkspaceWithBackEnd,
syncronizeSessionsFoundAtWorkspaceWithBackEnd: syncronizeSessionsFoundAtWorkspaceWithBackEnd,
syncronizeTradingSessionsFoundAtWorkspaceWithBackEnd: syncronizeTradingSessionsFoundAtWorkspaceWithBackEnd,
syncronizeLearningSessionsFoundAtWorkspaceWithBackEnd: syncronizeLearningSessionsFoundAtWorkspaceWithBackEnd,
playTutorials: playTutorials,
recreateWorkspace: recreateWorkspace,
getNodeById: getNodeById,
@@ -14,7 +15,8 @@ function newUiObjectsFromNodes() {
let mapOfReferenceChildren = new Map()
let mapOfNodes
let tasksFoundAtWorkspace
let sessionsFoundAtWorkspace
let tradingSessionsFoundAtWorkspace
let learningSessionsFoundAtWorkspace
let tutorialsToPlay
return thisObject
@@ -26,7 +28,8 @@ function newUiObjectsFromNodes() {
function recreateWorkspace(node, callBackFunction) {
mapOfNodes = new Map()
tasksFoundAtWorkspace = []
sessionsFoundAtWorkspace = []
tradingSessionsFoundAtWorkspace = []
learningSessionsFoundAtWorkspace = []
tutorialsToPlay = []
removeNullRootNodes()
@@ -163,12 +166,20 @@ function newUiObjectsFromNodes() {
tasksFoundAtWorkspace = undefined
}
function syncronizeSessionsFoundAtWorkspaceWithBackEnd(functionLibrarySessionFunctions) {
for (let i = 0; i < sessionsFoundAtWorkspace.length; i++) {
let node = sessionsFoundAtWorkspace[i]
function syncronizeTradingSessionsFoundAtWorkspaceWithBackEnd(functionLibrarySessionFunctions) {
for (let i = 0; i < tradingSessionsFoundAtWorkspace.length; i++) {
let node = tradingSessionsFoundAtWorkspace[i]
functionLibrarySessionFunctions.syncronizeSessionWithBackEnd(node)
}
sessionsFoundAtWorkspace = undefined
tradingSessionsFoundAtWorkspace = undefined
}
function syncronizeLearningSessionsFoundAtWorkspaceWithBackEnd(functionLibrarySessionFunctions) {
for (let i = 0; i < learningSessionsFoundAtWorkspace.length; i++) {
let node = learningSessionsFoundAtWorkspace[i]
functionLibrarySessionFunctions.syncronizeSessionWithBackEnd(node)
}
learningSessionsFoundAtWorkspace = undefined
}
function playTutorials() {
@@ -643,8 +654,13 @@ function newUiObjectsFromNodes() {
/* Check if there are sessions to run */
if (userAddingNew === false && node.savedPayload !== undefined) {
if (uiObjectType === 'Live Trading Session' || uiObjectType === 'Forward Testing Session' || uiObjectType === 'Backtesting Session' || uiObjectType === 'Paper Trading Session') {
if (sessionsFoundAtWorkspace !== undefined) { // it might be undefined when you are spawning a session that was running while backed up
sessionsFoundAtWorkspace.push(node)
if (tradingSessionsFoundAtWorkspace !== undefined) { // it might be undefined when you are spawning a session that was running while backed up
tradingSessionsFoundAtWorkspace.push(node)
}
}
if (uiObjectType === 'Learning Session') {
if (learningSessionsFoundAtWorkspace !== undefined) { // it might be undefined when you are spawning a session that was running while backed up
learningSessionsFoundAtWorkspace.push(node)
}
}
}
@@ -1 +1 @@
{"type":"Trading Mine","name":"Masters","config":"{ \n\"codeName\": \"Masters\"\n}","project":"Superalgos","tradingBots":[{"type":"Trading Bot","name":"Low Frequency","config":"{\n\"codeName\": \"Low-Frequency\",\n\"repo\": \"Exchange-Raw-Data-Sensor-Bot\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Trading","config":"{\n \"codeName\": \"Trading\",\n \"sessionRunWaitTime\": 5000,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Low-Frequency-Trading-Process\"\n }\n }","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[],"outputDatasetFolders":[{"type":"Output Dataset Folder","name":"Trading Engine","project":"Superalgos","outputDatasets":[],"outputDatasetFolders":[{"type":"Output Dataset Folder","name":"Episode","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Episode Counters","project":"Superalgos","id":"ec8d74ba-a4ad-417a-b479-6bae95b8a1fe","savedPayload":{"position":{"x":24910.97457254189,"y":18457.46644293786},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"3ed03a02-381d-43fe-9faa-761728c53bd8"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Counters","project":"Superalgos","id":"22b0af33-8c2f-4194-839b-affd18f298d5","savedPayload":{"position":{"x":24834.601232363748,"y":18490.07023931273},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"15f5b150-f1cf-403c-8cb9-2c7c4e1db8e8"}}},{"type":"Output Dataset","name":"Multi-Period-Market Episode Statistics","project":"Superalgos","id":"23ab91ae-2e78-4993-bb69-855f69cef1ce","savedPayload":{"position":{"x":24753.53736157276,"y":18508.085329665024},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"fc9dc0f7-35e0-4548-bb91-f920825d694f"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Statistics","project":"Superalgos","id":"d0a4515a-279d-4c27-8de2-168108861242","savedPayload":{"position":{"x":24670.543493063306,"y":18510.89823169951},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"91953362-8751-4440-a898-21245cd47c15"}}},{"type":"Output Dataset","name":"Multi-Period-Market Episode Candle","project":"Superalgos","id":"7fc80977-5b37-413e-8107-0a89a16e08b0","savedPayload":{"position":{"x":24588.445883487308,"y":18498.413155411115},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"17fb41f5-61b5-4433-9a10-950ff8216a7e"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Candle","project":"Superalgos","id":"a6888750-1043-420c-9253-633e1399c5e4","savedPayload":{"position":{"x":24510.040268473647,"y":18471.05526509864},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"bbc9467d-28bf-432b-9e49-582d1bcabfb9"}}},{"type":"Output Dataset","name":"Multi-Period-Market Episode Balances","project":"Superalgos","id":"0ad114df-f076-4a86-8c62-4c4a146da73c","savedPayload":{"position":{"x":24437.996657204443,"y":18429.756200904503},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"acddff59-b51b-4b45-b58f-71d4077755ee"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Balances","project":"Superalgos","id":"04b51302-957d-4365-ad55-9f89d60e261c","savedPayload":{"position":{"x":24374.76840845468,"y":18375.922352927064},"targetPosition":{"x":24696.86240363471,"y":18061.6685410663Line truncated
{"type":"Trading Mine","name":"Masters","config":"{ \n\"codeName\": \"Masters\"\n}","project":"Superalgos","tradingBots":[{"type":"Trading Bot","name":"Low Frequency","config":"{\n\"codeName\": \"Low-Frequency\",\n\"repo\": \"Exchange-Raw-Data-Sensor-Bot\"\n}","project":"Superalgos","processes":[{"type":"Process Definition","name":"Trading","config":"{\n \"codeName\": \"Trading\",\n \"sessionRunWaitTime\": 5000,\n \"retryWaitTime\": 10000,\n \"framework\": {\n \"name\": \"Low-Frequency-Trading-Process\"\n }\n }","project":"Superalgos","processOutput":{"type":"Process Output","name":"New Process Output","project":"Superalgos","outputDatasets":[],"outputDatasetFolders":[{"type":"Output Dataset Folder","name":"Trading Engine","project":"Superalgos","outputDatasets":[],"outputDatasetFolders":[{"type":"Output Dataset Folder","name":"Episode","project":"Superalgos","outputDatasets":[{"type":"Output Dataset","name":"Multi-Period-Market Episode Counters","project":"Superalgos","id":"ec8d74ba-a4ad-417a-b479-6bae95b8a1fe","savedPayload":{"position":{"x":24910.97457254189,"y":18457.46644293786},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"3ed03a02-381d-43fe-9faa-761728c53bd8"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Counters","project":"Superalgos","id":"22b0af33-8c2f-4194-839b-affd18f298d5","savedPayload":{"position":{"x":24834.601232363748,"y":18490.07023931273},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"15f5b150-f1cf-403c-8cb9-2c7c4e1db8e8"}}},{"type":"Output Dataset","name":"Multi-Period-Market Episode Statistics","project":"Superalgos","id":"23ab91ae-2e78-4993-bb69-855f69cef1ce","savedPayload":{"position":{"x":24753.53736157276,"y":18508.085329665024},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"fc9dc0f7-35e0-4548-bb91-f920825d694f"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Statistics","project":"Superalgos","id":"d0a4515a-279d-4c27-8de2-168108861242","savedPayload":{"position":{"x":24670.543493063306,"y":18510.89823169951},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"91953362-8751-4440-a898-21245cd47c15"}}},{"type":"Output Dataset","name":"Multi-Period-Market Episode Candle","project":"Superalgos","id":"7fc80977-5b37-413e-8107-0a89a16e08b0","savedPayload":{"position":{"x":24588.445883487308,"y":18498.413155411115},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"17fb41f5-61b5-4433-9a10-950ff8216a7e"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Candle","project":"Superalgos","id":"a6888750-1043-420c-9253-633e1399c5e4","savedPayload":{"position":{"x":24510.040268473647,"y":18471.05526509864},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"bbc9467d-28bf-432b-9e49-582d1bcabfb9"}}},{"type":"Output Dataset","name":"Multi-Period-Market Episode Balances","project":"Superalgos","id":"0ad114df-f076-4a86-8c62-4c4a146da73c","savedPayload":{"position":{"x":24437.996657204443,"y":18429.756200904503},"targetPosition":{"x":24696.86240363471,"y":18061.668541066385},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"acddff59-b51b-4b45-b58f-71d4077755ee"}}},{"type":"Output Dataset","name":"Multi-Period-Daily Episode Balances","project":"Superalgos","id":"04b51302-957d-4365-ad55-9f89d60e261c","savedPayload":{"position":{"x":24374.76840845468,"y":18375.922352927064},"targetPosition":{"x":24696.86240363471,"y":18061.6685410663Line truncated
@@ -1 +1 @@
{"type":"Workspace","name":"Exchange Keys Tests","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2017-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"f17f9567-af83-4292-a0dc-7c1c9dbf53b8","savedPayload":{"position":{"x":23993.925629940142,"y":29195.742554406977},"targetPosition":{"x":24261.227587196652,"y":29331.93970432884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"9eaa4440-c8bc-4daa-b858-efa1845087de","savedPayload":{"position":{"x":24261.227587196652,"y":29331.93970432884},"targetPosition":{"x":24528.529544453162,"y":29468.136854250704},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"97e5a05e-9463-41a4-8255-a9487df56496","savedPayload":{"position":{"x":24528.529544453162,"y":29468.136854250704},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Candles Volumes","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Candles Volumes","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"1ef6762d-a20c-46e0-8183-6aac6dd9073a","savedPayload":{"position":{"x":24447.0295945802,"y":28782.09892401185},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"9f683143-a33f-42c1-9fa8-c601f01ee4e1"}}},{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"7b44275e-9446-4807-b9c2-4ba1107a5295","savedPayload":{"position":{"x":24594.720518211823,"y":28734.111233969106},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"980ceb1d-7be6-454f-90d9-01ba1fd4a65d"}}}],"id":"78c835ef-be5b-4e74-8b0c-610afbbef304","savedPayload":{"position":{"x":24610.421305084707,"y":29033.700094395477},"targetPosition":{"x":24703.12640339719,"y":29319.017049284023},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"b4da2db7-fcae-4918-b38a-5e6966a9994b","savedPayload":{"position":{"x":24703.12640339719,"y":29319.017049284023},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Bollinger Bands","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Bollinger Bands","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Bollinger Bands Multi-Period-Market","project":"Superalgos","id":"22a8694f-078e-4f1f-8470-7a7b25237397","savedPayload":{"position":{"x":25130.599308798726,"y":28776.285809439407},"targetPosition":{"x":25068.2258015534,"y":29069.730089659548},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"941a0543-0cc0-4a5d-a782-728d2835c100"}}}Line truncated
{"type":"Workspace","name":"Exchange Keys Tests","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2017-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"f17f9567-af83-4292-a0dc-7c1c9dbf53b8","savedPayload":{"position":{"x":23993.925629940142,"y":29195.742554406977},"targetPosition":{"x":24261.227587196652,"y":29331.93970432884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"9eaa4440-c8bc-4daa-b858-efa1845087de","savedPayload":{"position":{"x":24261.227587196652,"y":29331.93970432884},"targetPosition":{"x":24528.529544453162,"y":29468.136854250704},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"97e5a05e-9463-41a4-8255-a9487df56496","savedPayload":{"position":{"x":24528.529544453162,"y":29468.136854250704},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Candles Volumes","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Candles Volumes","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"1ef6762d-a20c-46e0-8183-6aac6dd9073a","savedPayload":{"position":{"x":24447.0295945802,"y":28782.09892401185},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"9f683143-a33f-42c1-9fa8-c601f01ee4e1"}}},{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"7b44275e-9446-4807-b9c2-4ba1107a5295","savedPayload":{"position":{"x":24594.720518211823,"y":28734.111233969106},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"980ceb1d-7be6-454f-90d9-01ba1fd4a65d"}}}],"id":"78c835ef-be5b-4e74-8b0c-610afbbef304","savedPayload":{"position":{"x":24610.421305084707,"y":29033.700094395477},"targetPosition":{"x":24703.12640339719,"y":29319.017049284023},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"b4da2db7-fcae-4918-b38a-5e6966a9994b","savedPayload":{"position":{"x":24703.12640339719,"y":29319.017049284023},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Bollinger Bands","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Bollinger Bands","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Bollinger Bands Multi-Period-Market","project":"Superalgos","id":"22a8694f-078e-4f1f-8470-7a7b25237397","savedPayload":{"position":{"x":25130.599308798726,"y":28776.285809439407},"targetPosition":{"x":25068.2258015534,"y":29069.730089659548},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"941a0543-0cc0-4a5d-a782-728d2835c100"}}}Line truncated
@@ -1 +1 @@
{"type":"Workspace","name":"Getting Started","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"d244c564-4e86-43c7-9796-dc3b6294ec8b","savedPayload":{"position":{"x":23993.925629940142,"y":29195.742554406977},"targetPosition":{"x":24261.227587196652,"y":29331.93970432884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"343313ae-5705-484d-8bf8-aed25ba61cfa","savedPayload":{"position":{"x":24261.227587196652,"y":29331.93970432884},"targetPosition":{"x":24528.529544453162,"y":29468.136854250704},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"a8f38508-1cac-4ab1-815f-d338fc813377","savedPayload":{"position":{"x":24528.529544453162,"y":29468.136854250704},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Candles Volumes","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Candles Volumes","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"f0ef12ed-f0fd-4b88-8e15-27cf24265a5f","savedPayload":{"position":{"x":24387.47785744149,"y":28832.96091248782},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"9f683143-a33f-42c1-9fa8-c601f01ee4e1"}}},{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"7c8b312c-09bf-4c59-853f-1592391a9c57","savedPayload":{"position":{"x":24672.794812330034,"y":28740.255814175336},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"980ceb1d-7be6-454f-90d9-01ba1fd4a65d"}}}],"id":"8d58e84b-d7ef-464f-8079-0ec0887e3da3","savedPayload":{"position":{"x":24610.421305084707,"y":29033.700094395477},"targetPosition":{"x":24703.12640339719,"y":29319.017049284023},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"bf29e3bd-9386-408b-9091-042da0c53e81","savedPayload":{"position":{"x":24703.12640339719,"y":29319.017049284023},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Resistances and Supports","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Resistances and Supports","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Period-Market","project":"Superalgos","id":"a707814e-b81b-4102-9b5b-4e2fe969324f","savedPayload":{"position":{"x":25052.525014680516,"y":28770.141229233177},"targetPosition":{"x":25068.2258015534,"y":29069.730089659548},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"5d9b2729-43fb-4eLine truncated
{"type":"Workspace","name":"Getting Started","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"d244c564-4e86-43c7-9796-dc3b6294ec8b","savedPayload":{"position":{"x":23993.925629940142,"y":29195.742554406977},"targetPosition":{"x":24261.227587196652,"y":29331.93970432884},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"343313ae-5705-484d-8bf8-aed25ba61cfa","savedPayload":{"position":{"x":24261.227587196652,"y":29331.93970432884},"targetPosition":{"x":24528.529544453162,"y":29468.136854250704},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"a8f38508-1cac-4ab1-815f-d338fc813377","savedPayload":{"position":{"x":24528.529544453162,"y":29468.136854250704},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Candles Volumes","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Candles Volumes","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Market","project":"Superalgos","id":"f0ef12ed-f0fd-4b88-8e15-27cf24265a5f","savedPayload":{"position":{"x":24387.47785744149,"y":28832.96091248782},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"9f683143-a33f-42c1-9fa8-c601f01ee4e1"}}},{"type":"Indicator Process Instance","name":"Candles Volumes Multi-Period-Daily","project":"Superalgos","id":"7c8b312c-09bf-4c59-853f-1592391a9c57","savedPayload":{"position":{"x":24672.794812330034,"y":28740.255814175336},"targetPosition":{"x":24610.421305084707,"y":29033.700094395477},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"980ceb1d-7be6-454f-90d9-01ba1fd4a65d"}}}],"id":"8d58e84b-d7ef-464f-8079-0ec0887e3da3","savedPayload":{"position":{"x":24610.421305084707,"y":29033.700094395477},"targetPosition":{"x":24703.12640339719,"y":29319.017049284023},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"bf29e3bd-9386-408b-9091-042da0c53e81","savedPayload":{"position":{"x":24703.12640339719,"y":29319.017049284023},"targetPosition":{"x":24795.831501709672,"y":29604.334004172568},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Task","name":"Resistances and Supports","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Resistances and Supports","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Period-Market","project":"Superalgos","id":"a707814e-b81b-4102-9b5b-4e2fe969324f","savedPayload":{"position":{"x":25052.525014680516,"y":28770.141229233177},"targetPosition":{"x":25068.2258015534,"y":29069.730089659548},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"5d9b2729-43fb-4eLine truncated
@@ -1 +1 @@
{"type":"Workspace","name":"Weak-hands Buster v2","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Sparta","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Sparta","project":"Superalgos","tasks":[{"type":"Task","name":"EMA","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"EMA","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"EMA Multi-Period-Market","project":"Superalgos","id":"9adffd60-8756-44f0-9290-692711f43349","savedPayload":{"position":{"x":23796.023627541625,"y":29309.637679073698},"targetPosition":{"x":24089.467907761766,"y":29372.011186319025},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"278c34a7-199d-400e-8a06-087149e3d391"}}},{"type":"Indicator Process Instance","name":"EMA Multi-Period-Daily","project":"Superalgos","id":"559fc728-018a-4e8e-a5fa-1e37958e4f6c","savedPayload":{"position":{"x":23996.762809449283,"y":29086.69423143048},"targetPosition":{"x":24089.467907761766,"y":29372.011186319025},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"943ea24f-ee24-4eae-9b4b-e8a73122b1c2"}}}],"id":"82a8c05f-a6f6-4728-8271-7b327c2b72ee","savedPayload":{"position":{"x":24089.467907761766,"y":29372.011186319025},"targetPosition":{"x":24312.411355404984,"y":29572.750368226683},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8ae4fc50-8c1f-4e45-9ffd-fad368816b9a","savedPayload":{"position":{"x":24312.411355404984,"y":29572.750368226683},"targetPosition":{"x":24535.3548030482,"y":29773.48955013434},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"51b49b9d-cb97-4d98-ad8f-9f691320bac2","savedPayload":{"position":{"x":24535.3548030482,"y":29773.48955013434},"targetPosition":{"x":24758.29825069142,"y":29974.228732042},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"63728769-73e4-474e-8aa3-0d82bedca08e","savedPayload":{"position":{"x":24758.29825069142,"y":29974.228732042},"targetPosition":{"x":24981.241698334637,"y":30174.96791394966},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Sparta","id":"9cfffc48-486a-48cb-b641-98c82e314d3a"}}},{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"149bc037-9762-4737-b1b8-945b5ccee230","savedPayload":{"position":{"x":24503.771167102317,"y":28919.249010579722},"targetPosition":{"x":24704.510349009975,"y":29142.19245822294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"507bc325-1cbd-40f4-85eb-cfe77b78000e","savedPayload":{"position":{"x":24704.510349009975,"y":29142.19245822294},"targetPosition":{"x":24905.249530917634,"y":29365.13590586616},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"7c28a4a4-86da-43be-9e89-d01b202f27eb","savedPayload":{"position":{"x":24905.249530917634,"y":29365.13590586616},"targetPosition":{"x":25105.988712825292,"y":29588.079353509376},"floatingObject":{"isPiLine truncated
{"type":"Workspace","name":"Weak-hands Buster v2","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataMining":{"type":"Data Mining","name":"New Data Mining","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Sparta","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Sparta","project":"Superalgos","tasks":[{"type":"Task","name":"EMA","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"EMA","config":"{}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"EMA Multi-Period-Market","project":"Superalgos","id":"9adffd60-8756-44f0-9290-692711f43349","savedPayload":{"position":{"x":23796.023627541625,"y":29309.637679073698},"targetPosition":{"x":24089.467907761766,"y":29372.011186319025},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Market","id":"278c34a7-199d-400e-8a06-087149e3d391"}}},{"type":"Indicator Process Instance","name":"EMA Multi-Period-Daily","project":"Superalgos","id":"559fc728-018a-4e8e-a5fa-1e37958e4f6c","savedPayload":{"position":{"x":23996.762809449283,"y":29086.69423143048},"targetPosition":{"x":24089.467907761766,"y":29372.011186319025},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Period-Daily","id":"943ea24f-ee24-4eae-9b4b-e8a73122b1c2"}}}],"id":"82a8c05f-a6f6-4728-8271-7b327c2b72ee","savedPayload":{"position":{"x":24089.467907761766,"y":29372.011186319025},"targetPosition":{"x":24312.411355404984,"y":29572.750368226683},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"8ae4fc50-8c1f-4e45-9ffd-fad368816b9a","savedPayload":{"position":{"x":24312.411355404984,"y":29572.750368226683},"targetPosition":{"x":24535.3548030482,"y":29773.48955013434},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"51b49b9d-cb97-4d98-ad8f-9f691320bac2","savedPayload":{"position":{"x":24535.3548030482,"y":29773.48955013434},"targetPosition":{"x":24758.29825069142,"y":29974.228732042},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"63728769-73e4-474e-8aa3-0d82bedca08e","savedPayload":{"position":{"x":24758.29825069142,"y":29974.228732042},"targetPosition":{"x":24981.241698334637,"y":30174.96791394966},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Sparta","id":"9cfffc48-486a-48cb-b641-98c82e314d3a"}}},{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{ \n\"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"149bc037-9762-4737-b1b8-945b5ccee230","savedPayload":{"position":{"x":24503.771167102317,"y":28919.249010579722},"targetPosition":{"x":24704.510349009975,"y":29142.19245822294},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"507bc325-1cbd-40f4-85eb-cfe77b78000e","savedPayload":{"position":{"x":24704.510349009975,"y":29142.19245822294},"targetPosition":{"x":24905.249530917634,"y":29365.13590586616},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"7c28a4a4-86da-43be-9e89-d01b202f27eb","savedPayload":{"position":{"x":24905.249530917634,"y":29365.13590586616},"targetPosition":{"x":25105.988712825292,"y":29588.079353509376},"floatingObject":{"isPiLine truncated
File diff suppressed because it is too large. Load diff
@@ -1 +1 @@
[{"type":"Plotter Module","definition":"A plotter module is a device within a plotter that contains the definitions to create the visualization for a product definition.","content":["\r","\r","A single plotter may have several modules. Different modules may be used to plot each product of the bot, or as best suits the expected use-pattern.\r","\r","[![Plotter-Module-01](https://user-images.githubusercontent.com/13994516/71016077-eab41180-20f4-11ea-87e7-7262ff10a1ab.gif)](https://user-images.githubusercontent.com/13994516/71016077-eab41180-20f4-11ea-87e7-7262ff10a1ab.gif)\r","\r","{% include important.html content=\"For a bot to use a plotter, the corresponding product definition must establish a reference with the plotter module built to interpret the dataset.\" %}\r","\r","[![Plotter-Module-02-Product-Link](https://user-images.githubusercontent.com/13994516/71016079-eab41180-20f4-11ea-8afb-96321f9c68d8.gif)](https://user-images.githubusercontent.com/13994516/71016079-eab41180-20f4-11ea-8afb-96321f9c68d8.gif)\r","\r"],"folderName":"data_mine","adding":["\r","\r","To add a plotter module, select *Add Plotter Module* on the plotter node menu.\r","\r"],"configuring":["\r","\r","Select *Configure Plotter Module* on the menu to access the configuration.\r","\r","```json\r","{\r"," \"codeName\": \"Module Name\",\r"," \"isLegacy\": true,\r"," \"icon\": \"histogram\"\r","}\r","```\r","\r","* ```codeName``` is the name used in the code to refer to the module.\r","\r","* ```isLegacy``` is ```true``` for plotters modules developed entirely in JavaScript, and is ```false``` or doesn't show in the configuration for plotters built with the tools featured in the data mine hierarchy.\r","\r","* ```icon``` is the name of the image that illustrates the corresponding layer in the Layers Panel. In case the banner is not specified, the *default banner* is used. Current possible values are:\r","\r","\r","| Value | Image|\r","| :---: | :---: |\r","| ```default``` | ![Default-Banner](https://user-images.githubusercontent.com/13994516/70896073-5bbdd100-1ff0-11ea-84e3-5bd90475976f.png) |\r","| ```histogram``` | ![Histogram-Banner](https://user-images.githubusercontent.com/13994516/70896074-5bbdd100-1ff0-11ea-8dad-ccc6cfe64beb.png) |\r","| ```band``` | ![Bands-Banner](https://user-images.githubusercontent.com/13994516/70896072-5bbdd100-1ff0-11ea-8626-61c36bd22a3c.png) |\r","| ```moving-average``` | ![Moving-Average-Banner](https://user-images.githubusercontent.com/13994516/70896075-5bbdd100-1ff0-11ea-9909-dae33e57f65f.png) |\r","| ```oscillator``` | ![Oscillator-Banner](https://user-images.githubusercontent.com/13994516/70896076-5c566780-1ff0-11ea-8a5b-20077257c560.png) |\r","| ```trend``` | ![trends-banner](https://user-images.githubusercontent.com/13994516/70989177-744aeb80-20c3-11ea-88f5-d10473fa79b9.png) |\r","\r","Custom images may be added too. To do that:\r","\r","1. name the image in the following format: ```image-name.png```;\r","\r","1. place images in the ```WebServer\\Images\\Icons``` folder;\r","\r","1. in the configuration of the module, use the name as is (e.g.: ```\"icon\": \"image-name\"```)\r","\r"],"starting":["\r","\r","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r","\r"]},{"type":"Nodes Values"},{"type":"Nodes Highlights"},{"type":"Nodes Errors"},{"type":"Nodes Warnings"},{"type":"Nodes Infos"},{"type":"Nodes Status"},{"type":"Nodes Progress"},{"type":"Nodes Running"},{"type":"Nodes Announcements"},{"type":"Record Values"},{"type":"Shapes","definition":"The shapes node contains definitions of polygons and styles to be rendered on a per-period basis over the charts.","content":["\r","\r","A plotter recursively renders graphics for each period or candle. This means that a definition of what shapes need to be drawn for a single period is required. The plotter does the same thing for every period or candle that is visible on the screen at any point in time, for any time frame, as long as the corresponding data is available.\r","\r","[![Shapes-01-show-off](https://user-images.githubusercontent.com/13994516/71016080-eab41180-20f4-11ea-84c6-a514b87d568f.gif)](https://user-images.githubusercontent.com/13994516/71016080-eab41180-20f4-11ea-84c6-a514b87d568f.gif)\r","\r","In general terms, the process of defining what is going to be rendered on the screen consist of the following four steps:\r","\r"," 1. Identifying points defined by ```[x,y]``` coordinates\r"," 2. Defining polygons\r"," 3. Defining default styles\r"," 4. Defining conditional styles\r","\r"],"folderName":"data_mine","adding":["\r","\r","To add a shapes node, select *Add Shapes* on the plotter module menu.\r","\r"],"configuring":["\r","\r","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r","\r"],"starting":["\r","\r","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r","\r"]},{"type":"Plotter Panel","definition":"A plotter panel usually shows numerical representations of data over the charts on a small window or panel. Line truncated
[{"type":"Plotter Module","definition":"A plotter module is a device within a plotter that contains the definitions to create the visualization for a product definition.","content":["\r","\r","A single plotter may have several modules. Different modules may be used to plot each product of the bot, or as best suits the expected use-pattern.\r","\r","[![Plotter-Module-01](https://user-images.githubusercontent.com/13994516/71016077-eab41180-20f4-11ea-87e7-7262ff10a1ab.gif)](https://user-images.githubusercontent.com/13994516/71016077-eab41180-20f4-11ea-87e7-7262ff10a1ab.gif)\r","\r","{% include important.html content=\"For a bot to use a plotter, the corresponding product definition must establish a reference with the plotter module built to interpret the dataset.\" %}\r","\r","[![Plotter-Module-02-Product-Link](https://user-images.githubusercontent.com/13994516/71016079-eab41180-20f4-11ea-8afb-96321f9c68d8.gif)](https://user-images.githubusercontent.com/13994516/71016079-eab41180-20f4-11ea-8afb-96321f9c68d8.gif)\r","\r"],"folderName":"data_mine","adding":["\r","\r","To add a plotter module, select *Add Plotter Module* on the plotter node menu.\r","\r"],"configuring":["\r","\r","Select *Configure Plotter Module* on the menu to access the configuration.\r","\r","```json\r","{\r"," \"codeName\": \"Module Name\",\r"," \"isLegacy\": true,\r"," \"icon\": \"histogram\"\r","}\r","```\r","\r","* ```codeName``` is the name used in the code to refer to the module.\r","\r","* ```isLegacy``` is ```true``` for plotters modules developed entirely in JavaScript, and is ```false``` or doesn't show in the configuration for plotters built with the tools featured in the data mine hierarchy.\r","\r","* ```icon``` is the name of the image that illustrates the corresponding layer in the Layers Panel. In case the banner is not specified, the *default banner* is used. Current possible values are:\r","\r","\r","| Value | Image|\r","| :---: | :---: |\r","| ```default``` | ![Default-Banner](https://user-images.githubusercontent.com/13994516/70896073-5bbdd100-1ff0-11ea-84e3-5bd90475976f.png) |\r","| ```histogram``` | ![Histogram-Banner](https://user-images.githubusercontent.com/13994516/70896074-5bbdd100-1ff0-11ea-8dad-ccc6cfe64beb.png) |\r","| ```band``` | ![Bands-Banner](https://user-images.githubusercontent.com/13994516/70896072-5bbdd100-1ff0-11ea-8626-61c36bd22a3c.png) |\r","| ```moving-average``` | ![Moving-Average-Banner](https://user-images.githubusercontent.com/13994516/70896075-5bbdd100-1ff0-11ea-9909-dae33e57f65f.png) |\r","| ```oscillator``` | ![Oscillator-Banner](https://user-images.githubusercontent.com/13994516/70896076-5c566780-1ff0-11ea-8a5b-20077257c560.png) |\r","| ```trend``` | ![trends-banner](https://user-images.githubusercontent.com/13994516/70989177-744aeb80-20c3-11ea-88f5-d10473fa79b9.png) |\r","\r","Custom images may be added too. To do that:\r","\r","1. name the image in the following format: ```image-name.png```;\r","\r","1. place images in the ```WebServer\\Images\\Icons``` folder;\r","\r","1. in the configuration of the module, use the name as is (e.g.: ```\"icon\": \"image-name\"```)\r","\r"],"starting":["\r","\r","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r","\r"]},{"type":"Nodes Values"},{"type":"Nodes Highlights"},{"type":"Nodes Errors"},{"type":"Nodes Warnings"},{"type":"Nodes Infos"},{"type":"Nodes Status"},{"type":"Nodes Progress"},{"type":"Nodes Running"},{"type":"Nodes Announcements"},{"type":"Record Values"},{"type":"Shapes","definition":"The shapes node contains definitions of polygons and styles to be rendered on a per-period basis over the charts.","content":["\r","\r","A plotter recursively renders graphics for each period or candle. This means that a definition of what shapes need to be drawn for a single period is required. The plotter does the same thing for every period or candle that is visible on the screen at any point in time, for any time frame, as long as the corresponding data is available.\r","\r","[![Shapes-01-show-off](https://user-images.githubusercontent.com/13994516/71016080-eab41180-20f4-11ea-84c6-a514b87d568f.gif)](https://user-images.githubusercontent.com/13994516/71016080-eab41180-20f4-11ea-84c6-a514b87d568f.gif)\r","\r","In general terms, the process of defining what is going to be rendered on the screen consist of the following four steps:\r","\r"," 1. Identifying points defined by ```[x,y]``` coordinates\r"," 2. Defining polygons\r"," 3. Defining default styles\r"," 4. Defining conditional styles\r","\r"],"folderName":"data_mine","adding":["\r","\r","To add a shapes node, select *Add Shapes* on the plotter module menu.\r","\r"],"configuring":["\r","\r","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r","\r"],"starting":["\r","\r","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r","\r"]},{"type":"Plotter Panel","definition":"A plotter panel usually shows numerical representations of data over the charts on a small window or panel. Line truncated
@@ -134,7 +134,7 @@ function newPlottersManager() {
}
let productDefinition = layer.productDefinition
let bot = layer.bot
let dataMine = layer.dataMine
let mine = layer.mine
let exchange = layer.exchange
let plotterModule = layer.plotterModule
let session
@@ -142,15 +142,18 @@ function newPlottersManager() {
let tradingEngine
/*
A layer can be referencing a Data Product in two different branches of the Network hiriatchy.
In one of those braches we can get the Session node, at the other we Cannot.
A layer can be referencing a Data Product in 3 different branches of the Network hiriatchy.
Two of those branches have sessions.
*/
let sessionReference = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(layer.definition, 'Session Reference', undefined, false, true, true, true)
let sessionReference = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(layer.definition, 'Trading Session Reference', undefined, false, true, true, true)
if (sessionReference === undefined) {
sessionReference = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(layer.definition, 'Learning Session Reference', undefined, false, true, true, true)
}
if (sessionReference !== undefined) {
session = sessionReference.referenceParent
if (session === undefined) {
logger.write('[ERROR] initializePlotter -> Sessioin is Undefined at Session Reference -> Plotter will not be loaded. ')
logger.write('[ERROR] initializePlotter -> Session Reference without a Reference Parent -> Plotter will not be loaded. ')
return
}
/* From the session we might be able to reach the Trading System or the Trading Engine */
@@ -170,7 +173,7 @@ function newPlottersManager() {
let eventsServerClient = UI.projects.superalgos.spaces.designSpace.workspace.eventsServerClients.get(layer.networkNode.id)
storage.initialize(
dataMine,
mine,
bot,
session,
productDefinition,
@@ -192,7 +195,7 @@ function newPlottersManager() {
if (plotterModule.config.isLegacy !== true) {
plotter = newPlotter()
} else {
plotter = getNewPlotter(dataMine.config.codeName, plotterModule.parentNode.config.codeName, plotterModule.config.codeName)
plotter = getNewPlotter(mine.config.codeName, plotterModule.parentNode.config.codeName, plotterModule.config.codeName)
}
plotter.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
@@ -218,7 +221,7 @@ function newPlottersManager() {
let panel = plotterModule.panels[i]
let parameters = {
dataMine: dataMine.config.codeName,
mine: mine.config.codeName,
plotterCodeName: plotterModule.parentNode.config.codeName,
moduleCodeName: plotterModule.config.codeName,
panelNode: panel
@@ -114,7 +114,8 @@ function newWorkspace() {
function runTasksAndSessions() {
executeAction({ name: 'Syncronize Tasks', project: 'Superalgos' })
executeAction({ name: 'Syncronize Sessions', project: 'Superalgos' })
executeAction({ name: 'Syncronize Trading Sessions', project: 'Superalgos' })
executeAction({ name: 'Syncronize Learning Sessions', project: 'Superalgos' })
executeAction({ name: 'Play Tutorials', project: 'Superalgos' })
}
@@ -320,6 +321,10 @@ function newWorkspace() {
networkNode.dataMining.payload.uiObject.menu.internalClick('Stop All Exchange Data Tasks')
networkNode.dataMining.payload.uiObject.menu.internalClick('Stop All Exchange Data Tasks')
}
if (networkNode.learningMining !== undefined && networkNode.learningMining.payload !== undefined) {
networkNode.learningMining.payload.uiObject.menu.internalClick('Stop All Exchange Learning Tasks')
networkNode.learningMining.payload.uiObject.menu.internalClick('Stop All Exchange Learning Tasks')
}
if (networkNode.testingEnvironment !== undefined && networkNode.testingEnvironment.payload !== undefined) {
networkNode.testingEnvironment.payload.uiObject.menu.internalClick('Stop All Exchange Trading Tasks')
networkNode.testingEnvironment.payload.uiObject.menu.internalClick('Stop All Exchange Trading Tasks')
@@ -1381,6 +1381,7 @@ function newUiObject() {
function drawChainLine() {
if (UI.projects.superalgos.spaces.floatingSpace.drawChainLines === false) { return }
if (thisObject.payload.chainParent === undefined) { return }
if (thisObject.payload.chainParent.payload === undefined) {return}
let targetPoint = {
x: thisObject.payload.chainParent.payload.floatingObject.container.frame.position.x,
@@ -17,7 +17,7 @@ function newLayer() {
exchange: undefined,
bot: undefined,
productDefinition: undefined,
dataMine: undefined,
mine: undefined,
plotterModule: undefined,
exchangeIcon: undefined,
plotterTypeIcon: undefined,
@@ -135,7 +135,7 @@ function newLayer() {
thisObject.networkNode = undefined
thisObject.bot = undefined
thisObject.productDefinition = undefined
thisObject.dataMine = undefined
thisObject.mine = undefined
}
function initialize(callBackFunction) {
@@ -161,20 +161,23 @@ function newLayer() {
'->Layer->' +
'Data Product->' +
'Data Product Folder->Data Product Folder->Data Product Folder->Data Product Folder->Data Product Folder->' +
'Bot Products->Data Mine Products->Trading Mine Products->' +
'Bot Products->Data Mine Products->Trading Mine Products->Learning Mine Products->' +
'Market Data Products->Exchange Data Products->' +
'Session Reference->Market Trading Products->Exchange Trading Products->' +
'Data Mines Data->Trading Mines Data->Data Storage->Network Node->' +
'Trading Session Reference->Learning Session Reference->' +
'Market Trading Products->Exchange Trading Products->' +
'Market Learning Products->Exchange Learning Products->' +
'Data Mines Data->Trading Mines Data->Learning Mines Data->Data Storage->Network Node->' +
'Data Storage->Network Node->' +
'Backtesting Session->Paper Trading Session->Forward Testing Session->Live Trading Session->' +
'Learning Session->' +
'Trading System Reference->Trading Engine Reference->Trading System->Trading Engine->' +
'Market->Market Base Asset->Asset->' +
'Market Quoted Asset->Asset->' +
'Exchange Markets->Crypto Exchange->' +
'Product Definition->' +
'Product Definition Folder->Product Definition Folder->Product Definition Folder->Product Definition Folder->Product Definition Folder->' +
'Sensor Bot->Indicator Bot->Trading Bot->' +
'Data Mine->Trading Mine->' +
'Sensor Bot->Indicator Bot->Trading Bot->Learning Bot->' +
'Data Mine->Trading Mine->Learning Mine->' +
'Dataset Definition->' +
'Record Definition->Record Property->Formula->' +
'Data Building Procedure->Procedure Loop->Javascript Code->Procedure Initialization->Javascript Code->' +
@@ -228,17 +231,23 @@ function newLayer() {
if (thisObject.bot === undefined) {
thisObject.bot = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(thisObject.definition, 'Trading Bot', undefined, false, true, true, true)
}
if (thisObject.bot === undefined) {
thisObject.bot = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(thisObject.definition, 'Learning Bot', undefined, false, true, true, true)
}
if (thisObject.bot === undefined) {
thisObject.payload.uiObject.setErrorMessage('Bot not Found')
return
}
thisObject.dataMine = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(thisObject.definition, 'Data Mine', undefined, false, true, true, true)
if (thisObject.dataMine === undefined) {
thisObject.dataMine = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(thisObject.definition, 'Trading Mine', undefined, false, true, true, true)
if (thisObject.dataMine === undefined) {
thisObject.payload.uiObject.setErrorMessage('Data Mine or Trading Mine not Found')
return
thisObject.mine = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(thisObject.definition, 'Data Mine', undefined, false, true, true, true)
if (thisObject.mine === undefined) {
thisObject.mine = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(thisObject.definition, 'Trading Mine', undefined, false, true, true, true)
if (thisObject.mine === undefined) {
thisObject.mine = UI.projects.superalgos.utilities.meshes.findNodeInNodeMesh(thisObject.definition, 'Learning Mine', undefined, false, true, true, true)
if (thisObject.mine === undefined) {
thisObject.payload.uiObject.setErrorMessage('Data Mine or Trading Mine or Learning Mine not Found')
return
}
}
}
@@ -56,7 +56,7 @@ function newSuperalgosPanelSpace() {
panel.session = pSession
panel.initialize(pParameters.panelNode)
} else {
panel = getNewPlotterPanel(pParameters.dataMine, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelNode.config.codeName)
panel = getNewPlotterPanel(pParameters.mine, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelNode.config.codeName)
panel.fitFunction = UI.projects.superalgos.spaces.chartingSpace.fitFunction
panel.container.isVisibleFunction = UI.projects.superalgos.spaces.chartingSpace.isThisPointVisible
panel.session = pSession
+15 -3
View File
@@ -99,6 +99,9 @@
if (botNode === undefined) {
botNode = global.FIND_NODE_IN_NODE_MESH(outputDatasetNode, 'Trading Bot')
}
if (botNode === undefined) {
botNode = global.FIND_NODE_IN_NODE_MESH(outputDatasetNode, 'Learning Bot')
}
if (botNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition not attached to a Bot. Product Definition = ");
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
@@ -115,9 +118,18 @@
if (dataMineNode === undefined) {
let tradingMineNode = global.FIND_NODE_IN_NODE_MESH(outputDatasetNode, 'Trading Mine')
if (tradingMineNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Bot not attached to a Data Mine or a Trading Mine.");
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
let learningMineNode = global.FIND_NODE_IN_NODE_MESH(outputDatasetNode, 'Learning Mine')
if (learningMineNode === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Bot not attached to a Data Mine, Trading Mine or Learning Mine.");
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
} else {
if (tradingMineNode.config.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Learning Mine witn no codeName defined.");
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
}
} else {
if (tradingMineNode.config.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] start -> Trading Mine witn no codeName defined.");
+2 -2
View File
@@ -36,7 +36,7 @@
thisObject.nodeArray = global.FILTER_OUT_NODES_WITHOUT_REFERENCE_PARENT_FROM_NODE_ARRAY(thisObject.nodeArray)
} else {
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> It is not possible to not have process dependencies, which means not data dependencies.");
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> It is not possible not to have process dependencies, which means not data dependencies.");
callBackFunction(global.DEFAULT_OK_RESPONSE)
return
}
@@ -65,7 +65,7 @@
let skipCount = 0
/*
The current nodeArray that we have includes all the dependencies daclared in the Data Mine / Trading Mine
The current nodeArray that we have includes all the dependencies daclared in the Data Mine | Trading Mine | Learning Mine
process dependencies, minus the ones without reference parent, meaning that references Data Mines that are
not present at the workspace. From all the remaining dependencies there will be others that we need to
filter out, and they are the ones which the user does not have a data product anywhere on the network where
+7 -3
View File
@@ -80,10 +80,14 @@ exports.newDebugLog = function newDebugLog() {
let filePath = thisObject.bot.filePathRoot + "/Logs/" + thisObject.bot.process + "/"
if (thisObject.bot.SESSION !== undefined) {
filePath = filePath + thisObject.bot.SESSION.folderName + "/" + executionDatetime;
if (thisObject.bot.TRADING_SESSION !== undefined) {
filePath = filePath + thisObject.bot.TRADING_SESSION.folderName + "/" + executionDatetime;
} else {
filePath = filePath + executionDatetime;
if (thisObject.bot.LEARNING_SESSION !== undefined) {
filePath = filePath + thisObject.bot.LEARNING_SESSION.folderName + "/" + executionDatetime;
} else {
filePath = filePath + executionDatetime;
}
}
if (thisObject.bot.debug.year !== undefined) {
@@ -1,6 +1,6 @@
exports.newSession = function newSession(bot, parentLogger) {
exports.newLearningSession = function newLearningSession(bot, parentLogger) {
const MODULE_NAME = "Session"
const MODULE_NAME = "Learning Session"
const FULL_LOG = true;
let thisObject = {
@@ -15,16 +15,16 @@
function initialize(pProcessConfig, callBackFunction) {
try {
/* Initialize this info so that everything is logged propeerly */
bot.SESSION = {
bot.LEARNING_SESSION = {
name: bot.processNode.session.name,
id: bot.processNode.session.id
}
/* Set the folderName for early logging */
if (bot.processNode.session.config.folderName === undefined) {
bot.SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.SESSION.id
bot.LEARNING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.LEARNING_SESSION.id
} else {
bot.SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.processNode.session.config.folderName
bot.LEARNING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.processNode.session.config.folderName
}
/* Check if there is a session */
@@ -38,10 +38,10 @@
bot.sessionKey = bot.processNode.session.name + '-' + bot.processNode.session.type + '-' + bot.processNode.session.id
global.SESSION_MAP.set(bot.sessionKey, bot.sessionKey)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Session Status', undefined, bot.sessionKey, undefined, onSessionStatus)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Run Session', undefined, bot.sessionKey, undefined, onSessionRun)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Stop Session', undefined, bot.sessionKey, undefined, onSessionStop)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Resume Session', undefined, bot.sessionKey, undefined, onSessionResume)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Learning Session Status', undefined, bot.sessionKey, undefined, onSessionStatus)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Run Learning Session', undefined, bot.sessionKey, undefined, onSessionRun)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Stop Learning Session', undefined, bot.sessionKey, undefined, onSessionStop)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Resume Learning Session', undefined, bot.sessionKey, undefined, onSessionResume)
/* Connect this here so that it is accesible from other places */
bot.sessionError = sessionError
@@ -57,12 +57,12 @@
function onSessionStatus() {
if (bot.SESSION_STATUS === 'Running') {
let event = {
status: 'Session Runnning'
status: 'Learning Session Runnning'
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.sessionKey, 'Status Response', event)
} else {
let event = {
status: 'Not Session Runnning'
status: 'Learning Session Not Runnning'
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.sessionKey, 'Status Response', event)
}
@@ -79,11 +79,11 @@
/* We are going to run the Definition comming at the event. */
bot.TRADING_SYSTEM = JSON.parse(message.event.tradingSystem)
bot.TRADING_ENGINE = JSON.parse(message.event.tradingEngine)
bot.SESSION = JSON.parse(message.event.session)
bot.LEARNING_SESSION = JSON.parse(message.event.session)
bot.DEPENDENCY_FILTER = JSON.parse(message.event.dependencyFilter)
bot.RESUME = false
bot.FIRST_EXECUTION = true
bot.SESSION.stop = stopSession // stop function
bot.LEARNING_SESSION.stop = stopSession // stop function
setUpSessionFolderName()
@@ -93,7 +93,7 @@
socialBotsModule.initialize()
let allGood
switch (bot.SESSION.type) {
switch (bot.LEARNING_SESSION.type) {
case 'Backtesting Session': {
allGood = startBackTesting(message)
break
@@ -119,7 +119,7 @@
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] onSessionRun -> Stopping the Session now. ') }
}
socialBotsModule.sendMessage(bot.SESSION.type + " '" + bot.SESSION.name + "' is starting.")
socialBotsModule.sendMessage(bot.LEARNING_SESSION.type + " '" + bot.LEARNING_SESSION.name + "' is starting.")
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onSessionRun -> err = " + err.stack);
}
@@ -131,7 +131,7 @@
function onSessionResume(message) {
try {
if (bot.SESSION.stop === undefined) {
if (bot.LEARNING_SESSION.stop === undefined) {
parentLogger.write(MODULE_NAME, "[WARN] onSessionResume -> Event received to resume the Session that have never be ran before. ")
return
}
@@ -145,7 +145,7 @@
bot.RESUME = true
bot.STOP_SESSION = false
socialBotsModule.sendMessage(bot.SESSION.type + " '" + bot.SESSION.name + "' is resuming.")
socialBotsModule.sendMessage(bot.LEARNING_SESSION.type + " '" + bot.LEARNING_SESSION.name + "' is resuming.")
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onSessionResume -> err = " + err.stack);
}
@@ -153,11 +153,11 @@
function stopSession(commandOrigin) {
socialBotsModule.sendMessage(bot.SESSION.type + " '" + bot.SESSION.name + "' is stopping " + commandOrigin)
socialBotsModule.sendMessage(bot.LEARNING_SESSION.type + " '" + bot.LEARNING_SESSION.name + "' is stopping " + commandOrigin)
socialBotsModule.finalize()
bot.STOP_SESSION = true
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] stopSession -> Stopping the Session now. ') }
sessionInfo(bot.SESSION, commandOrigin)
sessionInfo(bot.LEARNING_SESSION, commandOrigin)
}
function setUpSessionFolderName() {
@@ -167,12 +167,12 @@
Set the folderName for logging, reports, context and data output
*/
let config
if (bot.SESSION.config !== undefined) {
config = bot.SESSION.config
if (bot.LEARNING_SESSION.config !== undefined) {
config = bot.LEARNING_SESSION.config
if (config.folderName === undefined) {
bot.SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.SESSION.id
bot.LEARNING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.LEARNING_SESSION.id
} else {
bot.SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.processNode.session.config.folderName
bot.LEARNING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.processNode.session.config.folderName
}
}
}
@@ -183,16 +183,16 @@
non critical is missing, we complete it with a default value.
*/
if (bot.SESSION.parameters === undefined) {
if (bot.LEARNING_SESSION.parameters === undefined) {
let errorMessage = "Session Node with no Parameters."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION, errorMessage)
bot.sessionError(bot.LEARNING_SESSION, errorMessage)
return false
}
/* Time Range */
if (bot.SESSION.parameters.timeRange === undefined) { // if the Time Range is missing we create a default one.
bot.SESSION.parameters.timeRange = {
if (bot.LEARNING_SESSION.parameters.timeRange === undefined) { // if the Time Range is missing we create a default one.
bot.LEARNING_SESSION.parameters.timeRange = {
name: 'Missing Time Range',
type: 'Time Range',
config: {
@@ -202,18 +202,18 @@
}
} else {
/* Check that we received valid dates */
if (bot.SESSION.type === 'Backtesting Session') {
if (isNaN(new Date(bot.SESSION.parameters.timeRange.config.initialDatetime)).valueOf()) {
if (bot.LEARNING_SESSION.type === 'Backtesting Session') {
if (isNaN(new Date(bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime)).valueOf()) {
let errorMessage = "sessionParameters.timeRange.config.initialDatetime is not a valid date."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters, errorMessage)
return false
}
}
if (isNaN(new Date(bot.SESSION.parameters.timeRange.config.finalDatetime)).valueOf()) {
if (isNaN(new Date(bot.LEARNING_SESSION.parameters.timeRange.config.finalDatetime)).valueOf()) {
let errorMessage = "sessionParameters.timeRange.config.initialDatetime is not a valid date."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters, errorMessage)
return false
}
}
@@ -222,7 +222,7 @@
let today = (new Date()).valueOf()
let aYearAgo = today - global.ONE_YEAR_IN_MILISECONDS
let aYearFromNow = today + global.ONE_YEAR_IN_MILISECONDS
switch (bot.SESSION.type) {
switch (bot.LEARNING_SESSION.type) {
case 'Backtesting Session': {
useDefaultDatetimes(aYearAgo, today)
break
@@ -248,81 +248,81 @@
*/
/* Initial Datetime */
if (bot.SESSION.type === 'Backtesting Session') {
if (bot.SESSION.parameters.timeRange.config.initialDatetime === undefined) {
bot.SESSION.parameters.timeRange.config.initialDatetime = initialDefault
if (bot.LEARNING_SESSION.type === 'Backtesting Session') {
if (bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime === undefined) {
bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime = initialDefault
} else {
bot.SESSION.parameters.timeRange.config.initialDatetime = (new Date(bot.SESSION.parameters.timeRange.config.initialDatetime)).valueOf()
bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime = (new Date(bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime)).valueOf()
}
} else {
/* Non backtest session can start from the past only if explicitly configured that way */
if (bot.SESSION.parameters.timeRange.config.initialDatetime === undefined || bot.SESSION.parameters.timeRange.config.allowStartingFromThePast !== true) {
bot.SESSION.parameters.timeRange.config.initialDatetime = initialDefault
if (bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime === undefined || bot.LEARNING_SESSION.parameters.timeRange.config.allowStartingFromThePast !== true) {
bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime = initialDefault
} else {
bot.SESSION.parameters.timeRange.config.initialDatetime = (new Date(bot.SESSION.parameters.timeRange.config.initialDatetime)).valueOf()
bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime = (new Date(bot.LEARNING_SESSION.parameters.timeRange.config.initialDatetime)).valueOf()
}
}
/* Final Datetime */
if (bot.SESSION.parameters.timeRange.config.finalDatetime === undefined) {
bot.SESSION.parameters.timeRange.config.finalDatetime = finalDefault
if (bot.LEARNING_SESSION.parameters.timeRange.config.finalDatetime === undefined) {
bot.LEARNING_SESSION.parameters.timeRange.config.finalDatetime = finalDefault
} else {
bot.SESSION.parameters.timeRange.config.finalDatetime = (new Date(bot.SESSION.parameters.timeRange.config.finalDatetime)).valueOf()
bot.LEARNING_SESSION.parameters.timeRange.config.finalDatetime = (new Date(bot.LEARNING_SESSION.parameters.timeRange.config.finalDatetime)).valueOf()
}
}
/* Time Frame */
if (bot.SESSION.parameters.timeFrame === undefined) {
if (bot.LEARNING_SESSION.parameters.timeFrame === undefined) {
let errorMessage = "Session Parameters Node with no Time Frame."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters, errorMessage)
return false
}
if (bot.SESSION.parameters.timeFrame.config.label === undefined) {
if (bot.LEARNING_SESSION.parameters.timeFrame.config.label === undefined) {
let errorMessage = "Session Parameters Node with no Time Frame Label configuration."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters.timeFrame, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters.timeFrame, errorMessage)
return false
}
bot.SESSION.parameters.timeFrame.config.value = getTimeFrameFromLabel(bot.SESSION.parameters.timeFrame.config.label)
if (bot.SESSION.parameters.timeFrame.config.value === undefined) {
bot.LEARNING_SESSION.parameters.timeFrame.config.value = getTimeFrameFromLabel(bot.LEARNING_SESSION.parameters.timeFrame.config.label)
if (bot.LEARNING_SESSION.parameters.timeFrame.config.value === undefined) {
let errorMessage = "Config error: label value not recognized. Try 01-min or 01-hs for example."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters.timeFrame, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters.timeFrame, errorMessage)
return false
}
/* Session Base Asset */
if (bot.SESSION.parameters.sessionBaseAsset === undefined) {
if (bot.LEARNING_SESSION.parameters.sessionBaseAsset === undefined) {
let errorMessage = "Session Parameters Node with no Session Base Asset."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters, errorMessage)
return false
}
if (bot.SESSION.parameters.sessionBaseAsset.config.initialBalance === undefined) {
if (bot.LEARNING_SESSION.parameters.sessionBaseAsset.config.initialBalance === undefined) {
let errorMessage = "Session Parameters Session Base Asset with no initialBalance configuration."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters.sessionBaseAsset, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters.sessionBaseAsset, errorMessage)
return false
}
/* Session Quoted Asset */
if (bot.SESSION.parameters.sessionQuotedAsset === undefined) {
if (bot.LEARNING_SESSION.parameters.sessionQuotedAsset === undefined) {
let errorMessage = "Session Parameters Node with no Session Quoted Asset."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters, errorMessage)
return false
}
if (bot.SESSION.parameters.sessionQuotedAsset.config.initialBalance === undefined) {
if (bot.LEARNING_SESSION.parameters.sessionQuotedAsset.config.initialBalance === undefined) {
let errorMessage = "Session Parameters Session Quoted Asset with no initialBalance configuration."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.sessionError(bot.SESSION.parameters.sessionQuotedAsset, errorMessage)
bot.sessionError(bot.LEARNING_SESSION.parameters.sessionQuotedAsset, errorMessage)
return false
}
/* Slippage */
if (bot.SESSION.parameters.slippage === undefined) { // if the Slippage is missing we create a default one.
bot.SESSION.parameters.slippage = {
if (bot.LEARNING_SESSION.parameters.slippage === undefined) { // if the Slippage is missing we create a default one.
bot.LEARNING_SESSION.parameters.slippage = {
name: 'Missing Slippage',
type: 'Slippage',
config: {
@@ -332,19 +332,19 @@
}
}
}
if (bot.SESSION.parameters.slippage.config.marketOrderRate === undefined) { // if the marketOrderRate is missing we create a default one.
bot.SESSION.parameters.slippage.config.marketOrderRate = 0
if (bot.LEARNING_SESSION.parameters.slippage.config.marketOrderRate === undefined) { // if the marketOrderRate is missing we create a default one.
bot.LEARNING_SESSION.parameters.slippage.config.marketOrderRate = 0
}
if (bot.SESSION.parameters.slippage.config.stopLoss === undefined) { // if the stopLoss is missing we create a default one.
bot.SESSION.parameters.slippage.config.stopLoss = 0
if (bot.LEARNING_SESSION.parameters.slippage.config.stopLoss === undefined) { // if the stopLoss is missing we create a default one.
bot.LEARNING_SESSION.parameters.slippage.config.stopLoss = 0
}
if (bot.SESSION.parameters.slippage.config.takeProfit === undefined) { // if the takeProfit is missing we create a default one.
bot.SESSION.parameters.slippage.config.takeProfit = 0
if (bot.LEARNING_SESSION.parameters.slippage.config.takeProfit === undefined) { // if the takeProfit is missing we create a default one.
bot.LEARNING_SESSION.parameters.slippage.config.takeProfit = 0
}
/* Fee Structure */
if (bot.SESSION.parameters.feeStructure === undefined) { // if the Fee Structure is missing we create a default one.
bot.SESSION.parameters.feeStructure = {
if (bot.LEARNING_SESSION.parameters.feeStructure === undefined) { // if the Fee Structure is missing we create a default one.
bot.LEARNING_SESSION.parameters.feeStructure = {
name: 'Missing Fee Structure',
type: 'Fee Structure',
config: {
@@ -353,11 +353,11 @@
}
}
}
if (bot.SESSION.parameters.feeStructure.config.maker === undefined) { // if the maker is missing we create a default one.
bot.SESSION.parameters.feeStructure.config.maker = 0
if (bot.LEARNING_SESSION.parameters.feeStructure.config.maker === undefined) { // if the maker is missing we create a default one.
bot.LEARNING_SESSION.parameters.feeStructure.config.maker = 0
}
if (bot.SESSION.parameters.feeStructure.config.taker === undefined) { // if the taker is missing we create a default one.
bot.SESSION.parameters.feeStructure.config.taker = 0
if (bot.LEARNING_SESSION.parameters.feeStructure.config.taker === undefined) { // if the taker is missing we create a default one.
bot.LEARNING_SESSION.parameters.feeStructure.config.taker = 0
}
return true
@@ -371,7 +371,7 @@
if (bot.KEY === undefined || bot.SECRET === undefined) {
let errorMessage = "Key 'codeName' or 'secret' not provided. Plese check that and try again."
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[ERROR] initialize -> startLiveTrading -> " + errorMessage); }
bot.sessionError(bot.SESSION, errorMessage)
bot.sessionError(bot.LEARNING_SESSION, errorMessage)
return false
}
return true
@@ -387,20 +387,20 @@
/* Reduce the balance */
let balancePercentage = 1 // This is the default value
if (bot.SESSION.config.balancePercentage !== undefined) {
balancePercentage = bot.SESSION.config.balancePercentage
if (bot.LEARNING_SESSION.config.balancePercentage !== undefined) {
balancePercentage = bot.LEARNING_SESSION.config.balancePercentage
}
bot.SESSION.parameters.sessionBaseAsset.config.initialBalance = bot.SESSION.parameters.sessionBaseAsset.config.initialBalance * balancePercentage / 100
bot.SESSION.parameters.sessionQuotedAsset.config.initialBalance = bot.SESSION.parameters.sessionQuotedAsset.config.initialBalance * balancePercentage / 100
bot.LEARNING_SESSION.parameters.sessionBaseAsset.config.initialBalance = bot.LEARNING_SESSION.parameters.sessionBaseAsset.config.initialBalance * balancePercentage / 100
bot.LEARNING_SESSION.parameters.sessionQuotedAsset.config.initialBalance = bot.LEARNING_SESSION.parameters.sessionQuotedAsset.config.initialBalance * balancePercentage / 100
bot.SESSION.parameters.sessionBaseAsset.config.minimumBalance = bot.SESSION.parameters.sessionBaseAsset.config.minimumBalance * balancePercentage / 100
bot.SESSION.parameters.sessionQuotedAsset.config.minimumBalance = bot.SESSION.parameters.sessionQuotedAsset.config.minimumBalance * balancePercentage / 100
bot.LEARNING_SESSION.parameters.sessionBaseAsset.config.minimumBalance = bot.LEARNING_SESSION.parameters.sessionBaseAsset.config.minimumBalance * balancePercentage / 100
bot.LEARNING_SESSION.parameters.sessionQuotedAsset.config.minimumBalance = bot.LEARNING_SESSION.parameters.sessionQuotedAsset.config.minimumBalance * balancePercentage / 100
bot.SESSION.parameters.sessionBaseAsset.config.maximumBalance = bot.SESSION.parameters.sessionBaseAsset.config.maximumBalance * balancePercentage / 100
bot.SESSION.parameters.sessionQuotedAsset.config.maximumBalance = bot.SESSION.parameters.sessionQuotedAsset.config.maximumBalance * balancePercentage / 100
bot.LEARNING_SESSION.parameters.sessionBaseAsset.config.maximumBalance = bot.LEARNING_SESSION.parameters.sessionBaseAsset.config.maximumBalance * balancePercentage / 100
bot.LEARNING_SESSION.parameters.sessionQuotedAsset.config.maximumBalance = bot.LEARNING_SESSION.parameters.sessionQuotedAsset.config.maximumBalance * balancePercentage / 100
pProcessConfig.normalWaitTime = bot.SESSION.parameters.timeFrame.config.value
pProcessConfig.normalWaitTime = bot.LEARNING_SESSION.parameters.timeFrame.config.value
return true
}
@@ -21,7 +21,7 @@ exports.newAnnouncements = function newAnnouncements(bot, logger) {
function finalize() {
tradingSystem = undefined
tradingEngine = undefined
bot.SESSION.messagesSent = undefined
bot.TRADING_SESSION.messagesSent = undefined
}
function makeAnnoucements(node) {
@@ -44,8 +44,8 @@ exports.newAnnouncements = function newAnnouncements(bot, logger) {
text = tradingSystem.formulas.get(announcement.formula.id)
}
if (bot.SESSION.socialBots !== undefined) {
bot.SESSION.socialBots.announce(text)
if (bot.TRADING_SESSION.socialBots !== undefined) {
bot.TRADING_SESSION.socialBots.announce(text)
tradingSystem.announcements.push([announcement.id, text])
} else {
tradingSystem.errors.push([announcement.id, 'Could not announce because session does not have Social Bots.'])
@@ -23,7 +23,7 @@ exports.newOrdersCalculations = function newOrdersCalculations(bot, logger) {
return thisObject
function initialize() {
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
tradingEngine = bot.simulationState.tradingEngine
tradingSystem = bot.simulationState.tradingSystem
}
@@ -23,7 +23,7 @@ exports.newOrdersSimulations = function newOrdersSimulations(bot, logger) {
return thisObject
function initialize() {
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
tradingEngine = bot.simulationState.tradingEngine
tradingSystem = bot.simulationState.tradingSystem
}
+2 -2
View File
@@ -45,7 +45,7 @@ exports.newSnapshots = function newSnapshots(bot, logger) {
function initialize() {
tradingEngine = bot.simulationState.tradingEngine
tradingSystem = bot.simulationState.tradingSystem
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
}
function finalize() {
@@ -322,7 +322,7 @@ exports.newSnapshots = function newSnapshots(bot, logger) {
fileContent = "" + fileContent + "";
let fileName = pFileName + '.csv';
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SNAPSHOTS_FOLDER_NAME;
let filePath = bot.filePathRoot + "/Output/" + bot.TRADING_SESSION.folderName + "/" + SNAPSHOTS_FOLDER_NAME;
filePath += '/' + fileName
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
@@ -25,7 +25,7 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
function initialize() {
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
initializeNodeMap(tradingEngine)
@@ -91,6 +91,17 @@ exports.newTradingEngine = function newTradingEngine(bot, logger) {
break
}
}
/*
We can not have the last begin or last end to be zero, because that would prevent
objects starting with lastBegin in zero to being saved on file. For that reason
we will do this:
*/
if (tradingEngine.current.episode.cycle.lastBegin.value === 0) {
tradingEngine.current.episode.cycle.lastBegin.value = tradingEngine.current.episode.cycle.begin.value
}
if (tradingEngine.current.episode.cycle.lastEnd.value === 0) {
tradingEngine.current.episode.cycle.lastEnd.value = tradingEngine.current.episode.cycle.end.value
}
}
function cloneValues(originNode, destinationNode) {
@@ -23,7 +23,7 @@ exports.newTradingEpisode = function newTradingEpisode(bot, logger, tradingEngin
function initialize() {
tradingSystem = bot.simulationState.tradingSystem
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
}
function finalize() {
@@ -24,7 +24,7 @@ exports.newTradingExecution = function newTradingExecution(bot, logger, tradingE
function initialize() {
tradingSystem = bot.simulationState.tradingSystem
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
tradingOrdersModule.initialize()
}
@@ -27,7 +27,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM
function initialize() {
tradingSystem = bot.simulationState.tradingSystem
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
exchangeAPIModule.initialize()
announcementsModule.initialize()
@@ -476,7 +476,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM
async function createOrderAtExchange(tradingSystemOrder, tradingEngineOrder) {
/* Filter by Session Type */
switch (bot.SESSION.type) {
switch (bot.TRADING_SESSION.type) {
case 'Backtesting Session': {
return true
}
@@ -503,7 +503,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM
async function checkExchangeEvents(tradingEngineStage, tradingSystemOrder, tradingEngineOrder) {
/* Filter by Session Type */
switch (bot.SESSION.type) {
switch (bot.TRADING_SESSION.type) {
case 'Backtesting Session': {
return true
}
@@ -613,7 +613,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM
function simulateCheckExchangeEvents(tradingEngineStage, tradingSystemOrder, tradingEngineOrder) {
/* Filter by Session Type */
switch (bot.SESSION.type) {
switch (bot.TRADING_SESSION.type) {
case 'Backtesting Session': {
break
}
@@ -839,7 +839,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM
function simulateCancelOrder(tradingEngineStage, tradingSystemOrder, tradingEngineOrder, exitType) {
/* Filter by Session Type */
switch (bot.SESSION.type) {
switch (bot.TRADING_SESSION.type) {
case 'Backtesting Session': {
break
}
@@ -870,7 +870,7 @@ exports.newTradingOrders = function newTradingOrders(bot, logger, tradingEngineM
async function exchangeCancelOrder(tradingEngineStage, tradingSystemOrder, tradingEngineOrder, exitType) {
/* Filter by Session Type */
switch (bot.SESSION.type) {
switch (bot.TRADING_SESSION.type) {
case 'Backtesting Session': {
return
}
@@ -3,7 +3,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, tradingEngineM
This module will load if necesary all the data outputs so that they can be appended with new
records if needed. After running the simulation, it will save all the data outputs.
*/
const MODULE_NAME = 'Trading Bot'
const MODULE_NAME = 'Trading Output'
let thisObject = {
initialize: initialize,
@@ -133,7 +133,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, tradingEngineM
if (dataset.config.type === 'Market Files') {
let fileName = 'Data.json'
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
let filePath = bot.filePathRoot + '/Output/' + bot.TRADING_SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
await readOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
@@ -149,7 +149,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, tradingEngineM
let dateForPath = tradingProcessDate.getUTCFullYear() + '/' + utilities.pad(tradingProcessDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(tradingProcessDate.getUTCDate(), 2);
let fileName = 'Data.json'
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
let filePath = bot.filePathRoot + '/Output/' + bot.TRADING_SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
await readOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
@@ -190,7 +190,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, tradingEngineM
if (dataset.config.type === 'Market Files') {
let fileName = 'Data.json'
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
let filePath = bot.filePathRoot + '/Output/' + bot.TRADING_SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel
await writeOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
@@ -206,7 +206,7 @@ exports.newTradingOutput = function newTradingOutput(bot, logger, tradingEngineM
let dateForPath = tradingProcessDate.getUTCFullYear() + '/' + utilities.pad(tradingProcessDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(tradingProcessDate.getUTCDate(), 2);
let fileName = 'Data.json'
let filePath = bot.filePathRoot + '/Output/' + bot.SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
let filePath = bot.filePathRoot + '/Output/' + bot.TRADING_SESSION.folderName + '/' + dataset.parentNode.config.codeName + '/' + dataset.config.codeName + '/' + timeFrameLabel + "/" + dateForPath
await writeOutputFile(fileName, filePath, dataset.parentNode.config.codeName)
}
@@ -31,7 +31,7 @@ exports.newTradingPosition = function newTradingPosition(bot, logger, tradingEng
function initialize() {
tradingSystem = bot.simulationState.tradingSystem
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
}
function finalize() {
@@ -103,7 +103,7 @@
This variable tell us which day we are standing at, specially while working
with Daily Files. From this Date is that we are going to load the Daily Files.
*/
bot.simulationState.tradingEngine.current.episode.processDate.value = global.REMOVE_TIME(bot.SESSION.parameters.timeRange.config.initialDatetime).valueOf()
bot.simulationState.tradingEngine.current.episode.processDate.value = global.REMOVE_TIME(bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime).valueOf()
}
/*
@@ -119,7 +119,7 @@
await processSingleFiles()
if (await processMarketFiles() === false) {
bot.sessionHeartBeat(undefined, undefined, 'Waiting for Data Mining to be run')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be run')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
@@ -141,17 +141,17 @@
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.
*/
bot.sessionHeartBeat(undefined, undefined, 'Waking up')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waking up')
buildCharts(chart)
if (checkThereAreCandles(chart) === true) {
bot.sessionHeartBeat(undefined, undefined, 'Running')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Running')
await generateOutput(chart)
bot.sessionHeartBeat(undefined, undefined, 'Saving')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Saving')
await writeProcessFiles()
bot.sessionHeartBeat(undefined, undefined, 'Sleeping')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Sleeping')
} else {
bot.sessionHeartBeat(undefined, undefined, 'Waiting for Data Mining to be up to date. No candles found at.')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be up to date. No candles found at.')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
@@ -159,7 +159,7 @@
} else {
/* We are processing Daily Files */
do {
global.EMIT_SESSION_STATUS(bot.SESSION_STATUS, bot.sessionKey)
global.EMIT_SESSION_STATUS(bot.TRADING_SESSION_STATUS, bot.TRADING_SESSIONKey)
/*
We update the Trading Process Date with the date calculated at the simulation.
We will use this date to load indicator and output files. After that we will
@@ -171,9 +171,9 @@
if (checkStopTaskGracefully() === false) { break }
if (checkStopProcessing() === false) { break }
bot.sessionHeartBeat(undefined, undefined, 'Waking up')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waking up')
if (await processDailyFiles() === false) {
bot.sessionHeartBeat(undefined, undefined, 'Waiting for Data Mining to be run')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be run')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
@@ -186,13 +186,13 @@
The process of generating the output includes the trading simulation.
*/
if (checkThereAreCandles(chart) === true) {
bot.sessionHeartBeat(undefined, undefined, 'Running')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Running')
await generateOutput(chart)
bot.sessionHeartBeat(undefined, undefined, 'Saving')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Saving')
await writeProcessFiles()
bot.sessionHeartBeat(undefined, undefined, 'Sleeping')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Sleeping')
} else {
bot.sessionHeartBeat(undefined, undefined, 'Waiting for Data Mining to be up to date')
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be up to date')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
@@ -219,7 +219,7 @@
callBackFunction(global.DEFAULT_OK_RESPONSE)
function checkThereAreCandles(chart) {
let sessionParameters = bot.SESSION.parameters
let sessionParameters = bot.TRADING_SESSION.parameters
let propertyName = 'at' + sessionParameters.timeFrame.config.label.replace('-', '')
let candles = chart[propertyName].candles
@@ -236,7 +236,7 @@
let statusReport;
/* We are going to use the start date as beging of market date. */
contextVariables.dateBeginOfMarket = global.REMOVE_TIME(bot.SESSION.parameters.timeRange.config.initialDatetime)
contextVariables.dateBeginOfMarket = global.REMOVE_TIME(bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime)
/*
Here we get the status report from the bot who knows which is the end of the market.
*/
@@ -371,7 +371,7 @@
dataFiles = new Map();
if (bot.SESSION.parameters.timeFrame.config.label === timeFrameLabel) {
if (bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel) {
currentTimeFrame = global.marketFilesPeriods[n][0];
currentTimeFrameLabel = global.marketFilesPeriods[n][1];
}
@@ -384,7 +384,7 @@
}
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) {
if (!(bot.SESSION.parameters.timeFrame.config.label === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
if (!(bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
continue
}
}
@@ -431,8 +431,8 @@
let dataRecord = dataFile[i]
let begin = dataRecord[beginIndex]
let end = dataRecord[endIndex]
if (end + timeFrame < bot.SESSION.parameters.timeRange.config.initialDatetime - 1) { continue } // /1 because we need the previous closed element
if (begin > bot.SESSION.parameters.timeRange.config.finalDatetime) { continue }
if (end + timeFrame < bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime - 1) { continue } // /1 because we need the previous closed element
if (begin > bot.TRADING_SESSION.parameters.timeRange.config.finalDatetime) { continue }
result.push(dataRecord)
}
return result
@@ -468,7 +468,7 @@
}
}
if (bot.SESSION.parameters.timeFrame.config.label === timeFrameLabel) {
if (bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel) {
currentTimeFrame = global.dailyFilePeriods[n][0];
currentTimeFrameLabel = global.dailyFilePeriods[n][1];
}
@@ -488,7 +488,7 @@
}
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) {
if (!(bot.SESSION.parameters.timeFrame.config.label === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
if (!(bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
continue
}
}
@@ -653,7 +653,7 @@
let fileContent = JSON.stringify(dataRange);
let fileName = '/Data.Range.json';
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + productCodeName + "/" + 'Multi-Period-Daily' + fileName;
let filePath = bot.filePathRoot + "/Output/" + bot.TRADING_SESSION.folderName + "/" + productCodeName + "/" + 'Multi-Period-Daily' + fileName;
let response = await fileStorage.asyncCreateTextFile(filePath, fileContent + '\n')
@@ -692,7 +692,7 @@
let fileContent = JSON.stringify(timeFramesArray)
let fileName = '/Time.Frames.json';
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + productCodeName + "/" + processType + fileName;
let filePath = bot.filePathRoot + "/Output/" + bot.TRADING_SESSION.folderName + "/" + productCodeName + "/" + processType + fileName;
let response = await fileStorage.asyncCreateTextFile(filePath, fileContent + '\n')
if (response.err.result !== global.DEFAULT_OK_RESPONSE.result) {
@@ -728,12 +728,12 @@
function checkIfSessionMustStop() {
if (bot.SESSION.type === 'Backtesting Session') {
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
/*
Backtests needs only one execution of this process to complete.
*/
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[IMPORTANT] checkIfSessionMustStop -> Backtesting Session Finished. Stopping the Session now. ') }
bot.SESSION.stop('Backtesting Session Finished.')
bot.TRADING_SESSION.stop('Backtesting Session Finished.')
}
}
}
@@ -20,7 +20,7 @@ exports.newTradingRecords = function newTradingRecords(bot, logger) {
function initialize(pOutputDatasetsMap) {
tradingEngine = bot.simulationState.tradingEngine
tradingSystem = bot.simulationState.tradingSystem
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
outputDatasetsMap = pOutputDatasetsMap // These are the files turned into arrays, stored in a Map by Product codeName.
}
@@ -4,7 +4,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, tradin
the execution at each loop cycle of the Trading System Protocol.
*/
const FULL_LOG = true
const MODULE_NAME = 'Trading Simulation -> ' + bot.SESSION.name
const MODULE_NAME = 'Trading Simulation -> ' + bot.TRADING_SESSION.name
let thisObject = {
finalize: finalize,
@@ -28,7 +28,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, tradin
let tradingSystem = bot.simulationState.tradingSystem
let tradingEngine = bot.simulationState.tradingEngine
let sessionParameters = bot.SESSION.parameters
let sessionParameters = bot.TRADING_SESSION.parameters
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> initialDatetime = ' + sessionParameters.timeRange.config.initialDatetime) }
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> finalDatetime = ' + sessionParameters.timeRange.config.finalDatetime) }
@@ -71,7 +71,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, tradin
This will happen when the sessionParameters.timeRange.config.initialDatetime is beyond the last candle available,
meaning that the dataSet needs to be updated with more up-to-date data.
*/
bot.SESSION.stop('Data is not up-to-date enough. Please start the Masters Data Mining Operation.')
bot.TRADING_SESSION.stop('Data is not up-to-date enough. Please start the Masters Data Mining Operation.')
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[IMPORTANT] runSimulation -> Data is not up-to-date enough. Stopping the Session now. ') }
return
}
@@ -210,7 +210,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, tradin
if (checkFinalDatetime() === false) {
closeEpisode('Final Datetime Reached')
breakLoop = true
bot.SESSION.stop('Final Datetime Reached')
bot.TRADING_SESSION.stop('Final Datetime Reached')
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[IMPORTANT] runSimulation -> Final Datetime Reached. Stopping the Session now. ') }
return
}
@@ -218,7 +218,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, tradin
if (checkMinimunAndMaximunBalance() === false) {
closeEpisode('Min or Max Balance Reached')
breakLoop = true
bot.SESSION.stop('Min or Max Balance Reached')
bot.TRADING_SESSION.stop('Min or Max Balance Reached')
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[IMPORTANT] runSimulation -> Min or Max Balance Reached. Stopping the Session now. ') }
return
}
@@ -276,7 +276,7 @@ exports.newTradingSimulation = function newTradingSimulation(bot, logger, tradin
let processingDate = heartBeatDate.getUTCFullYear() + '-' + utilities.pad(heartBeatDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(heartBeatDate.getUTCDate(), 2)
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Simulation ' + bot.sessionKey + ' Loop # ' + tradingEngine.current.episode.candle.index.value + ' @ ' + processingDate) }
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] runSimulation -> loop -> Simulation ' + bot.TRADING_SESSIONKey + ' Loop # ' + tradingEngine.current.episode.candle.index.value + ' @ ' + processingDate) }
/* Logging to console and disk */
if (global.areEqualDates(currentDate, new Date()) === false) {
@@ -47,7 +47,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
function initialize() {
tradingSystem = bot.simulationState.tradingSystem
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
tradingStrategyModule.initialize()
tradingPositionModule.initialize()
@@ -160,7 +160,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
announcementsModule.makeAnnoucements(triggerStage.triggerOn)
announcementsModule.makeAnnoucements(triggerStage)
if (bot.SESSION.type === 'Backtesting Session') {
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
if (sessionParameters.snapshots !== undefined) {
if (sessionParameters.snapshots.config.strategy === true) {
snapshotsModule.strategyEntry()
@@ -245,7 +245,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
announcementsModule.makeAnnoucements(triggerStage.takePosition)
announcementsModule.makeAnnoucements(strategy.openStage)
if (bot.SESSION.type === 'Backtesting Session') {
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
if (sessionParameters.snapshots !== undefined) {
if (sessionParameters.snapshots.config.position === true) {
snapshotsModule.positionEntry()
@@ -856,7 +856,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
function closePositionAndStrategy() {
/* Taking Position Snapshot */
if (bot.SESSION.type === 'Backtesting Session') {
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
if (sessionParameters.snapshots !== undefined) {
if (sessionParameters.snapshots.config.position === true) {
snapshotsModule.positionExit()
@@ -865,7 +865,7 @@ exports.newTradingStages = function newTradingStages(bot, logger, tradingEngineM
}
/* Taking Strategy Snapshot */
if (bot.SESSION.type === 'Backtesting Session') {
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
if (sessionParameters.snapshots !== undefined) {
if (sessionParameters.snapshots.config.strategy === true) {
snapshotsModule.strategyExit()
@@ -19,7 +19,7 @@ exports.newTradingStrategy = function newTradingStrategy(bot, logger, tradingEng
function initialize() {
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
}
function finalize() {
@@ -28,7 +28,7 @@ exports.newTradingSystem = function newTradingSystem(bot, logger, tradingEngineM
function initialize() {
tradingSystem = bot.simulationState.tradingSystem
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.SESSION.parameters
sessionParameters = bot.TRADING_SESSION.parameters
tradingSystem.conditions = new Map()
tradingSystem.formulas = new Map()
+8 -2
View File
@@ -32,6 +32,9 @@
if (botNode === undefined) {
botNode = global.FIND_NODE_IN_NODE_MESH(outputDataset, 'Sensor Bot')
}
if (botNode === undefined) {
botNode = global.FIND_NODE_IN_NODE_MESH(outputDataset, 'Learning Bot')
}
/* Some validations to verify that everything is in place. */
if (outputDataset.referenceParent !== undefined) {
@@ -119,6 +122,9 @@
if (botNode === undefined) {
botNode = global.FIND_NODE_IN_NODE_MESH(outputDataset, 'Sensor Bot')
}
if (botNode === undefined) {
botNode = global.FIND_NODE_IN_NODE_MESH(outputDataset, 'Learning Bot')
}
/* Some validations to verify that everything is in place. */
if (outputDataset.referenceParent !== undefined) {
@@ -138,11 +144,11 @@
}
if (botNode.parentNode !== undefined) {
if (botNode.parentNode.config.codeName === undefined) {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> codeName at Data Mine not defined. Data Mine = " + JSON.stringify(botNode.parentNode));
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> codeName at Mine not defined. Mine = " + JSON.stringify(botNode.parentNode));
throw (global.DEFAULT_FAIL_RESPONSE);
}
} else {
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> Bot not attached to a Data Mine or Trading Mine. Bot = " + JSON.stringify(botNode));
logger.write(MODULE_NAME, "[ERROR] raiseEvents -> Bot not attached to a Data Mine | Trading Mine | Learning Mine. Bot = " + JSON.stringify(botNode));
throw (global.DEFAULT_FAIL_RESPONSE);
}
} else {
@@ -0,0 +1,685 @@
exports.newLearningBot = function newLearningBot(bot, parentLogger) {
const MODULE_NAME = "Learning Bot";
const FULL_LOG = true;
const TRADING_PROCESS_MODULE = require(global.ROOT_DIR + '/LowFrequencyTrading/MachineLearningProcess.js');
const FILE_STORAGE = require('./FileStorage.js');
const SESSION = require(global.ROOT_DIR + 'TradingSession');
let fileStorage = FILE_STORAGE.newFileStorage(parentLogger);
let session = SESSION.newLearningSession(bot, parentLogger)
const DEBUG_MODULE = require(global.ROOT_DIR + 'DebugLog');
let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble.
let nextLoopTimeoutHandle;
let thisObject = {
initialize: initialize,
run: run
};
let processConfig;
return thisObject;
function initialize(pProcessConfig, callBackFunction) {
/* This function is exactly the same in the 3 modules representing the 2 different bot types loops. */
try {
processConfig = pProcessConfig;
if (bot.definedByUI === true) {
/* The code of the bot is defined at the UI. No need to load a file with the code. */
session.initialize(processConfig, callBackFunction)
}
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function run(callBackFunction) {
try {
/* Some initial values*/
let fixedTimeLoopIntervalHandle;
bot.STOP_SESSION = true;
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] run -> Stopping the Session now. ') }
/* Heartbeats sent to the UI */
bot.processHeartBeat = processHeartBeat
loop();
function loop() {
try {
processHeartBeat(undefined, undefined, "Running...")
function pad(str, max) {
str = str.toString();
return str.length < max ? pad(" " + str, max) : str;
}
/* For each loop we want to create a new log file. */
if (logger !== undefined) {
logger.finalize()
}
logger = DEBUG_MODULE.newDebugLog();
global.LOGGER_MAP.set(MODULE_NAME, logger)
logger.bot = bot;
logger.initialize();
bot.loopCounter++;
bot.loopStartTime = new Date().valueOf();
let nextWaitTime;
/* We tell the UI that we are running. */
processHeartBeat(undefined, undefined, "Running...")
/* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */
const UTILITIES = require(global.ROOT_DIR + 'CloudUtilities');
const STATUS_REPORT = require(global.ROOT_DIR + 'StatusReport');
const STATUS_DEPENDENCIES = require(global.ROOT_DIR + 'StatusDependencies');
const DATA_DEPENDENCIES = require(global.ROOT_DIR + 'DataDependencies');
const DATA_SET = require(global.ROOT_DIR + 'DataSet');
const PROCESS_EXECUTION_EVENTS = require(global.ROOT_DIR + 'ProcessExecutionEvents');
const PROCESS_OUTPUT = require(global.ROOT_DIR + 'ProcessOutput');
/* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */
bot.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution.
/* High level log entry */
console.log(new Date().toISOString() + " " + pad(bot.exchange, 20) + " " + pad(bot.market.baseAsset + '/' + bot.market.quotedAsset, 10) + " " + pad(bot.codeName, 30) + " " + pad(bot.process, 30)
+ " Main Loop # " + pad(Number(bot.loopCounter), 8) + " " + bot.processNode.session.type + " " + bot.processNode.session.name)
/* Checking if we need to need to emit any event */
if (bot.SESSION_STATUS === 'Idle' && bot.STOP_SESSION === false) {
bot.SESSION_STATUS = 'Running'
}
if (bot.SESSION_STATUS === 'Running' && bot.STOP_SESSION === true) {
bot.SESSION_STATUS = 'Stopped'
}
global.EMIT_SESSION_STATUS (bot.SESSION_STATUS, bot.sessionKey)
/* Checking if we should process this loop or not.*/
if (bot.STOP_SESSION === true) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> Waiting for " + bot.processNode.session.type + " " + bot.processNode.session.name + " to be run."); }
console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30)
+ " Waiting for " + bot.processNode.session.type + " " + bot.processNode.session.name + " to be run. ");
nextWaitTime = 'Waiting for Session';
loopControl(nextWaitTime);
return
}
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
let processExecutionEvents
let userBot;
let processFramework;
let statusDependencies;
let dataDependencies;
initializeProcessExecutionEvents();
function initializeProcessExecutionEvents() {
try {
processExecutionEvents = PROCESS_EXECUTION_EVENTS.newProcessExecutionEvents(bot, logger)
processExecutionEvents.initialize(processConfig, onInizialized);
function onInizialized(err) {
try {
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Execution finished well.");
startProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
return
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function startProcessExecutionEvents() {
try {
processExecutionEvents.start(onStarted);
function onStarted(err) {
try {
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Execution finished well.");
if (global.STOP_TASK_GRACEFULLY === true) {
loopControl()
return
}
initializeStatusDependencies();
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessExecutionEvents -> onStarted -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
return
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function initializeStatusDependencies() {
try {
statusDependencies = STATUS_DEPENDENCIES.newStatusDependencies(bot, logger, STATUS_REPORT, UTILITIES, PROCESS_OUTPUT);
statusDependencies.initialize(onInizialized);
function onInizialized(err) {
try {
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> onInizialized -> Execution finished well.");
initializeDataDependencies();
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeStatusDependencies -> onInizialized -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
return
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function initializeDataDependencies() {
try {
dataDependencies = DATA_DEPENDENCIES.newDataDependencies(bot, logger, DATA_SET);
dataDependencies.initialize(onInizialized);
function onInizialized(err) {
try {
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); }
switch (processConfig.framework.name) {
case 'Low-Frequency-Trading-Process': {
processFramework = TRADING_PROCESS_MODULE.newMachineLearningProcess(bot, logger, UTILITIES);
intitializeProcessFramework();
break;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework not Supported.");
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework Name = " + processConfig.framework.name);
global.unexpectedError = err.message
processStopped()
return
}
}
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeDataDependencies -> onInizialized -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
return
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function intitializeProcessFramework() {
try {
processFramework.initialize(processConfig, statusDependencies, dataDependencies, onInizialized);
function onInizialized(err) {
try {
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> onInizialized -> Execution finished well.");
startProcessFramework();
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeProcessFramework -> onInizialized -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
return
}
case global.CUSTOM_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized > Unhandled custom response received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function startProcessFramework() {
try {
processFramework.start(onFinished);
function onFinished(err) {
try {
processFramework.finalize()
processFramework = undefined
dataDependencies.finalize()
dataDependencies = undefined
statusDependencies.finalize()
statusDependencies = undefined
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Execution finished well.");
nextWaitTime = 'Normal';
finishProcessExecutionEvents()
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
return
}
case global.CUSTOM_OK_RESPONSE.result: {
switch (err.message) {
case "Dependency does not exist.": {
logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency does not exist. This Loop will go to sleep.");
nextWaitTime = 'Sleep';
loopControl(nextWaitTime);
return;
}
case "Dependency not ready.": {
logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency not ready. This Loop will go to sleep.");
nextWaitTime = 'Sleep';
loopControl(nextWaitTime);
return;
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled custom response received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function finishProcessExecutionEvents() {
try {
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
processExecutionEvents.finalize()
processExecutionEvents = undefined
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Execution finished well.");
nextWaitTime = 'Normal';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time.
logger.write(MODULE_NAME, "[WARN] run -> loop -> finishProcessExecutionEvents -> onFinished -> Retry Later. Requesting Execution Retry.");
nextWaitTime = 'Retry';
loopControl(nextWaitTime);
return;
}
case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
return
}
default: {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err.result = " + err.result);
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err = " + err.message);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function loopControl(nextWaitTime) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> nextWaitTime = " + nextWaitTime); }
/* We show we reached the end of the loop. */
processHeartBeat(undefined, undefined, "Running...")
/* Here we check if we must stop the loop gracefully. */
shallWeStop(onStop, onContinue);
function onStop() {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onStop -> Stopping the Loop Gracefully. See you next time!"); }
if (global.WRITE_LOGS_TO_FILES === 'true') {
logger.persist();
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.sessionKey, 'Stopped')
processStopped()
return;
}
function onContinue() {
/* Indicator bots are going to be executed after a configured period of time after the last execution ended. This is to avoid overlapping executions. */
switch (nextWaitTime) {
case 'Waiting for Session': {
let waitTime = processConfig.sessionRunWaitTime
nextLoopTimeoutHandle = setTimeout(loop, waitTime);
let waitingTime = waitTime / 1000 / 60
let label = 'minute/s'
if (waitingTime < 1) {
waitingTime = waitTime / 1000
label = 'seconds'
}
processHeartBeat(undefined, undefined, "Waiting " + waitingTime + " " + label + " for " + bot.processNode.session.type + " " + bot.processNode.session.name + " to be run. ")
logger.persist();
}
break
case 'Normal': {
let waitTime
if (processConfig.waitsForExecutionFinishedEvent === true) {
waitTime = 0
} else {
switch (bot.LEARNING_SESSION.type) {
case 'Live Trading Session': {
waitTime = bot.LEARNING_SESSION.parameters.timeFrame.config.value
break
}
case 'Fordward Tessting Session': {
waitTime = bot.LEARNING_SESSION.parameters.timeFrame.config.value
break
}
case 'Paper Trading Session': {
waitTime = bot.LEARNING_SESSION.parameters.timeFrame.config.value
break
}
case 'Backtesting Session': {
waitTime = 0
break
}
}
}
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (waitTime / 1000 / 60) + " minute/s."); }
nextLoopTimeoutHandle = setTimeout(loop, waitTime);
let waitingTime = waitTime / 1000 / 60
let label = 'minute/s'
if (waitingTime < 1) {
waitingTime = waitTime / 1000
label = 'seconds'
}
processHeartBeat(undefined, undefined, "Waiting " + waitingTime + " " + label + " for next execution.")
logger.persist();
}
break;
case 'Retry': {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.retryWaitTime / 1000) + " seconds."); }
nextLoopTimeoutHandle = setTimeout(loop, processConfig.retryWaitTime);
processHeartBeat(undefined, undefined, "Trying to recover from some problem. Waiting " + processConfig.retryWaitTime / 1000 + " seconds for next execution.")
logger.persist();
}
break;
case 'Sleep': {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.sleepWaitTime / 60000) + " minutes."); }
nextLoopTimeoutHandle = setTimeout(loop, processConfig.sleepWaitTime);
processHeartBeat(undefined, undefined, "Waiting " + processConfig.sleepWaitTime / 60000 + " minutes for next execution.")
logger.persist();
}
break;
case 'Coma': {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.comaWaitTime / 3600000) + " hours."); }
nextLoopTimeoutHandle = setTimeout(loop, processConfig.comaWaitTime);
processHeartBeat(undefined, undefined, "Waiting " + processConfig.comaWaitTime / 3600000 + " hours for next execution.")
logger.persist();
}
break;
}
}
}
function shallWeStop(stopCallBack, continueCallBack) {
try {
/* IMPORTANT: This function is exactly the same on the 3 modules. */
if (!global.STOP_TASK_GRACEFULLY) {
continueCallBack();
} else {
stopCallBack();
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function processHeartBeat(processingDate, percentage, status) {
let event = {
seconds: (new Date()).getSeconds(),
processingDate: processingDate,
percentage: percentage,
status: status
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Heartbeat', event)
}
function processStopped() {
if (global.unexpectedError !== undefined) {
global.PROCESS_ERROR(bot.processKey, undefined, "An unexpected error caused the Process to stop.")
} else {
global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Stopped')
}
sessionStopped()
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
if (global.unexpectedError !== undefined) {
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
} else {
callBackFunction(global.DEFAULT_OK_RESPONSE)
}
}
function sessionStopped() {
if (bot.SESSION_STATUS === 'Running') {
global.EVENT_SERVER_CLIENT.raiseEvent(bot.sessionKey, 'Stopped')
bot.SESSION_STATUS = 'Stopped'
}
}
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] run -> err = " + err.stack);
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
};
@@ -0,0 +1,786 @@
exports.newLearningProcess = function newLearningProcess(bot, logger, UTILITIES) {
/*
This Module will load all the process data dependencies from files and send them downstream.
After execution, will save the time range and status report of the process.
*/
const FULL_LOG = true;
const MODULE_NAME = "Learning Process";
const GMT_SECONDS = ':00.000 GMT+0000';
thisObject = {
initialize: initialize,
finalize: finalize,
start: start
};
let utilities = UTILITIES.newCloudUtilities(logger);
let statusDependencies;
let dataDependenciesModule;
let dataFiles = new Map();
let multiPeriodDataFiles = new Map();
const FILE_STORAGE = require('../FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage(logger);
const MARKOV_DECISION_PROCESS_MODULE = require('./MarkovDecisionProcess.js')
let markovDecisionProcessModule = MARKOV_DECISION_PROCESS_MODULE.newMarkovDecisionProcess(bot, logger)
let ALGORITHM_MODULE = require("./Algorithm")
let algorithmModule = ALGORITHM_MODULE.newTradingOutput(bot, logger, markovDecisionProcessModule, UTILITIES, FILE_STORAGE)
let processConfig;
return thisObject;
function initialize(pProcessConfig, pStatusDependencies, pDataDependencies, callBackFunction) {
try {
logger.fileName = MODULE_NAME
logger.initialize()
statusDependencies = pStatusDependencies
dataDependenciesModule = pDataDependencies
processConfig = pProcessConfig
algorithmModule.initialize()
callBackFunction(global.DEFAULT_OK_RESPONSE)
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function finalize() {
markovDecisionProcessModule.finalize()
markovDecisionProcessModule = undefined
algorithmModule.finalize()
algorithmModule = undefined
dataFiles = undefined
multiPeriodDataFiles = undefined
statusDependencies = undefined
dataDependenciesModule = undefined
fileStorage = undefined
processConfig = undefined
thisObject = undefined
}
async function start(callBackFunction) {
try {
let currentTimeFrame
let currentTimeFrameLabel
/* Context Variables */
let contextVariables = {
lastFile: undefined, // Datetime of the last file files sucessfully produced by this process.
dateBeginOfMarket: undefined, // Datetime of the first trade file in the whole market history.
dateEndOfMarket: undefined // Datetime of the last file available to be used as an input of this process.
};
getContextVariables()
if (bot.FIRST_EXECUTION === true && bot.RESUME === false) {
/*
Here is where the Trading Engine and Trading Systems received are moved to the simulation state.
*/
bot.simulationState.tradingEngine = bot.TRADING_ENGINE
bot.simulationState.tradingSystem = bot.TRADING_SYSTEM
}
/* We set up the Trading Engine Module. */
markovDecisionProcessModule.initialize()
/* Initializing the Trading Process Date */
if (bot.FIRST_EXECUTION === true && bot.RESUME === false) {
/*
This funcion is going to be called many times by the Trading Bot Loop.
Only during the first execution and when the User is not resuming the execution
of a stopped session / task; we are going to initialize the Process Date Time.
This variable tell us which day we are standing at, specially while working
with Daily Files. From this Date is that we are going to load the Daily Files.
*/
bot.simulationState.tradingEngine.current.episode.processDate.value = global.REMOVE_TIME(bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime).valueOf()
}
/*
This is the Date that is going to be used across the execution of this Trading Process.
We need this because it has a different life cycle than the processData stored at the
Trading Engine data structure. This date has to remain the same during the whole execution
of the Trading Process until the end, inclusind the writting of Data Ranges and Status Reports.
The processDate of the Trading Engine data structure on the other hand can be changed during
the simulation loop, once we discover that all candles from a certain date have benn processed.
Here is the point where we sync one and the other.
*/
let LearningProcessDate = global.REMOVE_TIME(bot.simulationState.tradingEngine.current.episode.processDate.value)
await processSingleFiles()
if (await processMarketFiles() === false) {
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be run')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
/*
This is the Data Structure used at the Simulation with all indicator data.
We start creating it right here.
*/
let chart = {}
/*
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
dependencies on Daily Files. The way we recognize that is by checking if
we alreaady set a value to currentTimeFrame. We are also not going to loop
through days if we are processing market files.
*/
if (currentTimeFrame) {
/* We are processing Market Files */
/*
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.
*/
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waking up')
buildCharts(chart)
if (checkThereAreCandles(chart) === true) {
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Running')
await generateOutput(chart)
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Saving')
await writeProcessFiles()
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Sleeping')
} else {
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be up to date. No candles found at.')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
} else {
/* We are processing Daily Files */
do {
global.EMIT_SESSION_STATUS(bot.TRADING_SESSION_STATUS, bot.TRADING_SESSIONKey)
/*
We update the Trading Process Date with the date calculated at the simulation.
We will use this date to load indicator and output files. After that we will
use it to save Output Files and later the Data Ranges. This is the point where
the date calculated by the Simulation is applied at the Trading Process Level.
*/
LearningProcessDate = global.REMOVE_TIME(bot.simulationState.tradingEngine.current.episode.processDate.value)
if (checkStopTaskGracefully() === false) { break }
if (checkStopProcessing() === false) { break }
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waking up')
if (await processDailyFiles() === false) {
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be run')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
/*
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)
/*
The process of generating the output includes the trading simulation.
*/
if (checkThereAreCandles(chart) === true) {
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Running')
await generateOutput(chart)
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Saving')
await writeProcessFiles()
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Sleeping')
} else {
bot.TRADING_SESSIONHeartBeat(undefined, undefined, 'Waiting for Data Mining to be up to date')
callBackFunction(global.DEFAULT_RETRY_RESPONSE)
return
}
/*
If for any reason the session was stopped, we will break this loop and exit the process.
*/
if (bot.STOP_SESSION === true) { break }
/*
When we get to the end of the market, we need to break this process loop in order
to let time pass, new information be collected from the exchange, new data built
into indicators, and eventually a new execution of this process.
*/
if (checkStopHeadOfTheMarket() === false) { break }
}
while (true)
}
checkIfSessionMustStop()
/*
Everything worked as expected. We return an OK code and wait for
the Bot Loop to call us again later.
*/
callBackFunction(global.DEFAULT_OK_RESPONSE)
function checkThereAreCandles(chart) {
let sessionParameters = bot.TRADING_SESSION.parameters
let propertyName = 'at' + sessionParameters.timeFrame.config.label.replace('-', '')
let candles = chart[propertyName].candles
if (candles.length === 0) {
return false
} else {
return true
}
}
function getContextVariables() {
try {
let thisReport;
let statusReport;
/* We are going to use the start date as beging of market date. */
contextVariables.dateBeginOfMarket = global.REMOVE_TIME(bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime)
/*
Here we get the status report from the bot who knows which is the end of the market.
*/
statusReport = statusDependencies.reportsByMainUtility.get("Market Ending Point")
if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month.
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ");
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
return
}
if (statusReport.status === "Status Report is corrupt.") {
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. ");
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
return
}
thisReport = statusReport.file;
if (thisReport.lastFile === undefined) {
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> thisReport = " + JSON.stringify(thisReport));
let customOK = {
result: global.CUSTOM_OK_RESPONSE.result,
message: "Dependency not ready."
}
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message);
callBackFunction(customOK);
return
}
contextVariables.dateEndOfMarket = new Date(thisReport.lastFile.valueOf());
/* Finally we get our own Status Report. */
statusReport = statusDependencies.reportsByMainUtility.get("Self Reference")
if (statusReport === undefined) { // This means the status report does not exist, that could happen for instance at the begining of a month.
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Status Report does not exist. Retrying Later. ");
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
return
}
if (statusReport.status === "Status Report is corrupt.") {
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process.");
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
thisReport = statusReport.file;
bot.simulationState = thisReport.simulationState;
if (bot.simulationState === undefined) { bot.simulationState = {} } // This should happen only when there is no status report
if (thisReport.lastFile !== undefined) {
if (bot.RESUME !== true) {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Starting from the begining because bot has just started and resume execution was true."); }
startFromBegining();
return
}
contextVariables.lastFile = new Date(thisReport.lastFile);
return
} else {
/*
We are here becuse either:
1. There is no status report
2. There is no Last File (this happens on Market Files)
*/
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Starting from the begining of the market because own status report not found or lastFile was undefined."); }
startFromBegining();
return
}
function startFromBegining() {
contextVariables.lastFile = new Date(contextVariables.dateBeginOfMarket.getUTCFullYear() + "-" + (contextVariables.dateBeginOfMarket.getUTCMonth() + 1) + "-" + contextVariables.dateBeginOfMarket.getUTCDate() + " " + "00:00" + GMT_SECONDS);
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> startFromBegining -> contextVariables.lastFile = " + contextVariables.lastFile); }
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> err = " + err.stack);
if (err.message === "Cannot read property 'file' of undefined") {
logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Check the bot configuration to see if all of its statusDependencies declarations are correct. ");
logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys));
}
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
async function processSingleFiles() {
dataFiles = new Map();
for (let dependencyIndex = 0; dependencyIndex < dataDependenciesModule.nodeArray.length; dependencyIndex++) {
let dependency = dataDependenciesModule.nodeArray[dependencyIndex];
let datasetModule = dataDependenciesModule.dataSetsModulesArray[dependencyIndex];
if (datasetModule.node.config.codeName !== "Single-File") {
continue
}
if (dataDependenciesModule.isItADepenency('atAnyTimeFrame', datasetModule.node.parentNode.config.singularVariableName) !== true) {
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 asyncGetDatasetFile(datasetModule, filePath, fileName)
if (response.err.result !== global.DEFAULT_OK_RESPONSE.result) {
throw (response.err)
}
let dataFile = JSON.parse(response.text);
dataFiles.set(dependency.id, dataFile);
}
let mapKey = "Single Files"
multiPeriodDataFiles.set(mapKey, dataFiles)
}
async function processMarketFiles() {
/*
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 posible timeFrames.
*/
for (let n = 0; n < global.marketFilesPeriods.length; n++) {
const timeFrame = global.marketFilesPeriods[n][0];
const timeFrameLabel = global.marketFilesPeriods[n][1];
dataFiles = new Map();
if (bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel) {
currentTimeFrame = global.marketFilesPeriods[n][0];
currentTimeFrameLabel = global.marketFilesPeriods[n][1];
}
for (let dependencyIndex = 0; dependencyIndex < dataDependenciesModule.nodeArray.length; dependencyIndex++) {
let dependency = dataDependenciesModule.nodeArray[dependencyIndex];
let datasetModule = dataDependenciesModule.dataSetsModulesArray[dependencyIndex];
if (dependency.referenceParent.config.codeName !== "Multi-Period-Market") {
continue
}
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) {
if (!(bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
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 asyncGetDatasetFile(datasetModule, filePath, fileName)
if (response.err.message === 'File does not exist.') {
return false
}
if (response.err.result !== global.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 period 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]
if (end + timeFrame < bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime - 1) { continue } // /1 because we need the previous closed element
if (begin > bot.TRADING_SESSION.parameters.timeRange.config.finalDatetime) { continue }
result.push(dataRecord)
}
return result
}
}
let mapKey = global.marketFilesPeriods[n][1];
multiPeriodDataFiles.set(mapKey, dataFiles)
}
return true
}
async function processDailyFiles() {
/* Telling the world we are alive and doing well and which date we are processing right now. */
let processingDateString = LearningProcessDate.getUTCFullYear() + '-' + utilities.pad(LearningProcessDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(LearningProcessDate.getUTCDate(), 2);
bot.processHeartBeat(processingDateString, undefined, "Running...")
/*
We will iterate through all posible timeFrames.
*/
for (let n = 0; n < global.dailyFilePeriods.length; n++) {
const timeFrame = global.dailyFilePeriods[n][0];
const timeFrameLabel = global.dailyFilePeriods[n][1];
if (processConfig.framework.validtimeFrames !== undefined) {
let validPeriod = false;
for (let i = 0; i < processConfig.framework.validtimeFrames.length; i++) {
let period = processConfig.framework.validtimeFrames[i];
if (period === timeFrameLabel) { validPeriod = true }
}
if (validPeriod === false) {
continue
}
}
if (bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel) {
currentTimeFrame = global.dailyFilePeriods[n][0];
currentTimeFrameLabel = global.dailyFilePeriods[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.nodeArray.length; dependencyIndex++) {
let dependency = dataDependenciesModule.nodeArray[dependencyIndex];
let datasetModule = dataDependenciesModule.dataSetsModulesArray[dependencyIndex];
if (dependency.referenceParent.config.codeName !== "Multi-Period-Daily") {
continue
}
if (dataDependenciesModule.isItADepenency(timeFrameLabel, datasetModule.node.parentNode.config.singularVariableName) !== true) {
if (!(bot.TRADING_SESSION.parameters.timeFrame.config.label === timeFrameLabel && datasetModule.node.parentNode.config.pluralVariableName === 'candles')) {
continue
}
}
let dateForPath = LearningProcessDate.getUTCFullYear() + '/' + utilities.pad(LearningProcessDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(LearningProcessDate.getUTCDate(), 2);
let filePath
if (dependency.referenceParent.config.codeName === "Multi-Period-Daily") {
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + timeFrameLabel + "/" + dateForPath;
} else {
filePath = dependency.referenceParent.parentNode.config.codeName + '/' + dependency.referenceParent.config.codeName + "/" + 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 asyncGetDatasetFile(datasetModule, filePath, fileName)
if (response.err.message === 'File does not exist.') {
return false
}
if (response.err.result !== global.DEFAULT_OK_RESPONSE.result) {
throw (response.err)
}
let dataFile = JSON.parse(response.text);
dataFiles.set(dependency.id, dataFile);
}
let mapKey = global.dailyFilePeriods[n][1];
multiPeriodDataFiles.set(mapKey, dataFiles)
}
return true
}
function checkStopHeadOfTheMarket() {
/*
We need to check if we have reached the head of the market in order to know
when to break the Daily Files Process loop and give time for a new candles /
indicators to be built and continue the processing once this process is called
again.
*/
if (bot.simulationState.tradingEngine.current.episode.headOfTheMarket.value === true) {
return false
}
}
function checkStopTaskGracefully() {
/* Validation that we dont need to stop. */
if (global.STOP_TASK_GRACEFULLY === true) {
return false
}
}
function checkStopProcessing() {
/* Validation that we dont need to stop. */
if (bot.STOP_SESSION === true) {
return false
}
}
function buildCharts(chart) {
const COMMONS = require('../Commons.js')
let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE)
let mainDependency = {}
/* The first phase here is about checking that we have everything we need at the definition level. */
let dataDependencies = global.NODE_BRANCH_TO_ARRAY(bot.processNode.referenceParent.processDependencies, 'Data Dependency')
/*
We will filter ourt declared dependencies that are not present in the workspace.
This will allow the user to have less Data Mines loaded at the workspace
that the ones that a Trading Mine depends on.
*/
dataDependencies = global.FILTER_OUT_NODES_WITHOUT_REFERENCE_PARENT_FROM_NODE_ARRAY(dataDependencies)
if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) { return }
let outputDatasets = global.NODE_BRANCH_TO_ARRAY(bot.processNode.referenceParent.processOutput, 'Output Dataset')
if (commons.validateOutputDatasets(outputDatasets, callBackFunction) !== true) { return }
/* The second phase is about transforming the inputs into a format that can be used to apply the user defined code. */
for (let j = 0; j < global.marketFilesPeriods.length; j++) {
let timeFrameLabel = marketFilesPeriods[j][1]
let dataFiles = multiPeriodDataFiles.get(timeFrameLabel)
let products = {}
if (dataFiles !== undefined) {
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, currentTimeFrame)
let propertyName = 'at' + timeFrameLabel.replace('-', '')
chart[propertyName] = products
}
}
for (let j = 0; j < global.dailyFilePeriods.length; j++) {
let timeFrameLabel = global.dailyFilePeriods[j][1]
let dataFiles = multiPeriodDataFiles.get(timeFrameLabel)
let products = {}
if (dataFiles !== undefined) {
commons.inflateDatafiles(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) {
commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, currentTimeFrame)
let propertyName = 'atAnyTimeFrame'
chart[propertyName] = products
}
}
async function generateOutput(chart) {
await algorithmModule.start(
chart,
currentTimeFrame,
currentTimeFrameLabel,
LearningProcessDate
)
/*
From here on, all other loops executions wont be the first execution and also
we will consider that it is not resuming a previous execution as well.
*/
bot.FIRST_EXECUTION = false
bot.RESUME = false
}
async function writeProcessFiles() {
let outputDatasets = global.NODE_BRANCH_TO_ARRAY(bot.processNode.referenceParent.processOutput, 'Output Dataset')
await writeTimeFramesFiles(currentTimeFrame, currentTimeFrameLabel)
await writeDataRanges()
if (currentTimeFrame > global.dailyFilePeriods[0][0]) {
await writeMarketStatusReport(currentTimeFrameLabel)
} else {
await writeDailyStatusReport(currentTimeFrameLabel)
}
async function writeDataRanges() {
for (
let outputDatasetIndex = 0;
outputDatasetIndex < outputDatasets.length;
outputDatasetIndex++
) {
let productCodeName = outputDatasets[outputDatasetIndex].referenceParent.parentNode.config.codeName;
await writeDataRange(productCodeName);
}
async function writeDataRange(productCodeName) {
let dataRange = {
begin: contextVariables.dateBeginOfMarket.valueOf(),
end: LearningProcessDate.valueOf() + global.ONE_DAY_IN_MILISECONDS
}
let fileContent = JSON.stringify(dataRange);
let fileName = '/Data.Range.json';
let filePath = bot.filePathRoot + "/Output/" + bot.TRADING_SESSION.folderName + "/" + productCodeName + "/" + 'Multi-Period-Daily' + fileName;
let response = await fileStorage.asyncCreateTextFile(filePath, fileContent + '\n')
if (response.err.result !== global.DEFAULT_OK_RESPONSE.result) {
throw (response.err)
}
/*
Raise the event that the Data Range was Updated.
*/
let key = bot.dataMine + "-" + bot.codeName + "-" + productCodeName + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
let event = {
dateRange: dataRange
}
global.EVENT_SERVER_CLIENT.raiseEvent(key, 'Data Range Updated', event)
}
}
async function writeTimeFramesFiles(currentTimeFrame, currentTimeFrameLabel) {
for (
let outputDatasetIndex = 0;
outputDatasetIndex < outputDatasets.length;
outputDatasetIndex++
) {
let productCodeName = outputDatasets[outputDatasetIndex].referenceParent.parentNode.config.codeName;
await writeTimeFramesFile(currentTimeFrameLabel, productCodeName, 'Multi-Period-Daily')
await writeTimeFramesFile(currentTimeFrameLabel, productCodeName, 'Multi-Period-Market')
async function writeTimeFramesFile(currentTimeFrameLabel, productCodeName, processType) {
let timeFramesArray = []
timeFramesArray.push(currentTimeFrameLabel)
let fileContent = JSON.stringify(timeFramesArray)
let fileName = '/Time.Frames.json';
let filePath = bot.filePathRoot + "/Output/" + bot.TRADING_SESSION.folderName + "/" + productCodeName + "/" + processType + fileName;
let response = await fileStorage.asyncCreateTextFile(filePath, fileContent + '\n')
if (response.err.result !== global.DEFAULT_OK_RESPONSE.result) {
throw (response.err)
}
}
}
}
async function writeDailyStatusReport(currentTimeFrameLabel) {
let reportKey = bot.dataMine + "-" + bot.codeName + "-" + bot.processNode.referenceParent.config.codeName
let thisReport = statusDependencies.statusReports.get(reportKey)
thisReport.file.lastExecution = bot.currentDaytime
thisReport.file.lastFile = LearningProcessDate
thisReport.file.simulationState = bot.simulationState
thisReport.file.timeFrames = currentTimeFrameLabel
await thisReport.asyncSave()
}
async function writeMarketStatusReport(currentTimeFrameLabel) {
let reportKey = bot.dataMine + "-" + bot.codeName + "-" + bot.processNode.referenceParent.config.codeName
let thisReport = statusDependencies.statusReports.get(reportKey);
thisReport.file.lastExecution = bot.processDatetime
thisReport.file.simulationState = bot.simulationState
thisReport.file.timeFrames = currentTimeFrameLabel
logger.newInternalLoop(bot.codeName, bot.process, LearningProcessDate)
await thisReport.asyncSave()
}
}
function checkIfSessionMustStop() {
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
/*
Backtests needs only one execution of this process to complete.
*/
if (FULL_LOG === true) { logger.write(MODULE_NAME, '[IMPORTANT] checkIfSessionMustStop -> Backtesting Session Finished. Stopping the Session now. ') }
bot.TRADING_SESSION.stop('Backtesting Session Finished.')
}
}
}
catch (err) {
/* An unhandled exception occured. in this case we return Fail and log the stack. */
if (err.stack) {
logger.write(MODULE_NAME, "[ERROR] start -> Unhandled Exception. Will Abort this process. err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
/* Some expected file was not found. We will return a RETRY code and move on. */
if ((err.result === "Fail Because" && err.message === "File does not exist.") || err.code === 'The specified key does not exist.') {
logger.write(MODULE_NAME, "[ERROR] File not Found. Will Retry the Process Loop.")
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
return
}
/* Some other handled exception occured. We return Fail and move on. */
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] start -> Handled Exception. Will Abort this process. err = " + err.message);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return
}
}
}
function pad(str, max) {
str = str.toString();
return str.length < max ? pad(" " + str, max) : str;
}
async function asyncGetDatasetFile(datasetModule, filePath, fileName) {
let promise = new Promise((resolve, reject) => {
datasetModule.getTextFile(filePath, fileName, onFileReceived);
function onFileReceived(err, text) {
let response = {
err: err,
text: text
}
resolve(response)
}
});
return promise
}
}
@@ -0,0 +1,218 @@
exports.newMarkovDecisionProcess = function newMarkovDecisionProcess(bot, logger) {
/*
We call the Trading Engine to the data structure that is needed in order to exevute the
trading protocol with the specific rules defined at the Trading System.
*/
const MODULE_NAME = 'Markov Decision Process'
let thisObject = {
mantain: mantain,
reset: reset,
getNodeById: getNodeById,
cloneValues: cloneValues,
setCurrentCandle: setCurrentCandle,
setCurrentCycle: setCurrentCycle,
initializeNode: initializeNode,
initialize: initialize,
finalize: finalize
}
let tradingEngine
let sessionParameters
let nodesMap = new Map()
return thisObject
function initialize() {
tradingEngine = bot.simulationState.tradingEngine
sessionParameters = bot.LEARNING_SESSION.parameters
initializeNodeMap(tradingEngine)
if (bot.FIRST_EXECUTION === true) {
/*
Here we will go through all the nodes in the Trading Engine hiriarchy and
apply the initial value to the value property when needed
*/
initializeNode(tradingEngine)
}
}
function finalize() {
tradingEngine = undefined
sessionParameters = undefined
nodesMap = undefined
}
function mantain() {
}
function reset() {
}
function getNodeById(NodeId) {
return nodesMap.get(NodeId)
}
function setCurrentCandle(candle) {
tradingEngine.current.episode.candle.begin.value = candle.begin
tradingEngine.current.episode.candle.end.value = candle.end
tradingEngine.current.episode.candle.open.value = candle.open
tradingEngine.current.episode.candle.close.value = candle.close
tradingEngine.current.episode.candle.min.value = candle.min
tradingEngine.current.episode.candle.max.value = candle.max
}
function setCurrentCycle(cycle) {
tradingEngine.current.episode.cycle.value = cycle
tradingEngine.current.episode.cycle.lastBegin.value = tradingEngine.current.episode.cycle.begin.value
tradingEngine.current.episode.cycle.lastEnd.value = tradingEngine.current.episode.cycle.end.value
switch (cycle) {
case 'First': {
tradingEngine.current.episode.cycle.begin.value =
tradingEngine.current.episode.candle.begin.value +
sessionParameters.timeFrame.config.value
tradingEngine.current.episode.cycle.end.value =
tradingEngine.current.episode.candle.begin.value +
sessionParameters.timeFrame.config.value +
sessionParameters.timeFrame.config.value / 2 - 1
break
}
case 'Second': {
tradingEngine.current.episode.cycle.begin.value =
tradingEngine.current.episode.candle.begin.value +
sessionParameters.timeFrame.config.value +
sessionParameters.timeFrame.config.value / 2
tradingEngine.current.episode.cycle.end.value =
tradingEngine.current.episode.candle.begin.value +
sessionParameters.timeFrame.config.value +
sessionParameters.timeFrame.config.value * 4 / 4 - 1
break
}
}
}
function cloneValues(originNode, destinationNode) {
if (originNode === undefined) { return }
if (destinationNode === undefined) { return }
/* Here copy the node value */
destinationNode.value = originNode.value
/* Now we go down through all the children of the origin node, assuming the destination node has the same children structure*/
let nodeDefinition = global.APP_SCHEMA_MAP.get(originNode.type)
if (nodeDefinition === undefined) { return }
if (nodeDefinition.properties !== undefined) {
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
for (let i = 0; i < nodeDefinition.properties.length; i++) {
let property = nodeDefinition.properties[i]
switch (property.type) {
case 'node': {
if (property.name !== previousPropertyName) {
if (originNode[property.name] !== undefined && destinationNode[property.name] !== undefined) {
cloneValues(originNode[property.name], destinationNode[property.name])
}
previousPropertyName = property.name
}
break
}
case 'array': {
if (originNode[property.name] !== undefined && destinationNode[property.name] !== undefined) {
let originNodePropertyArray = originNode[property.name]
let destinationNodePropertyArray = destinationNode[property.name]
for (let m = 0; m < originNodePropertyArray.length; m++) {
cloneValues(originNodePropertyArray[m], destinationNodePropertyArray[m])
}
}
break
}
}
}
}
}
function initializeNodeMap(node) {
if (node === undefined) { return }
/* Add to Node Map */
nodesMap.set(node.id, node)
/* Now we go down through all this node children */
let nodeDefinition = global.APP_SCHEMA_MAP.get(node.type)
if (nodeDefinition === undefined) { return }
if (nodeDefinition.properties !== undefined) {
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
for (let i = 0; i < nodeDefinition.properties.length; i++) {
let property = nodeDefinition.properties[i]
switch (property.type) {
case 'node': {
if (property.name !== previousPropertyName) {
if (node[property.name] !== undefined) {
initializeNodeMap(node[property.name])
}
previousPropertyName = property.name
}
break
}
case 'array': {
if (node[property.name] !== undefined) {
let nodePropertyArray = node[property.name]
for (let m = 0; m < nodePropertyArray.length; m++) {
initializeNodeMap(nodePropertyArray[m])
}
}
break
}
}
}
}
}
function initializeNode(node) {
if (node === undefined) { return }
/* Here we initialize the node value */
if (node.config !== undefined) {
if (node.config.initialValue !== undefined) {
node.value = node.config.initialValue
}
}
/* Now we go down through all this node children */
let nodeDefinition = global.APP_SCHEMA_MAP.get(node.type)
if (nodeDefinition === undefined) { return }
if (nodeDefinition.properties !== undefined) {
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
for (let i = 0; i < nodeDefinition.properties.length; i++) {
let property = nodeDefinition.properties[i]
switch (property.type) {
case 'node': {
if (property.name !== previousPropertyName) {
if (node[property.name] !== undefined) {
initializeNode(node[property.name])
}
previousPropertyName = property.name
}
break
}
case 'array': {
if (node[property.name] !== undefined) {
let nodePropertyArray = node[property.name]
for (let m = 0; m < nodePropertyArray.length; m++) {
initializeNode(nodePropertyArray[m])
}
}
break
}
}
}
}
}
}
+77
View File
@@ -266,6 +266,10 @@
runTradingBot(botConfig, processConfig);
break;
}
case 'Learning Bot': {
runLearningBot(botConfig, processConfig);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
@@ -296,6 +300,10 @@
runTradingBot(botConfig, processConfig);
break;
}
case 'Learning Bot': {
runLearningBot(botConfig, processConfig);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
@@ -339,6 +347,10 @@
runTradingBot(botConfig, processConfig);
break;
}
case 'Learning Bot': {
runLearningBot(botConfig, processConfig);
break;
}
default: {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> Unexpected bot type. -> botConfig.type = " + botConfig.type);
}
@@ -540,6 +552,71 @@
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
function runLearningBot(pBotConfig, pProcessConfig) {
global.TOTAL_PROCESS_INSTANCES_CREATED++
try {
const DEBUG_MODULE = require(global.ROOT_DIR + 'DebugLog');
let logger;
logger = DEBUG_MODULE.newDebugLog();
global.LOGGER_MAP.set('runLearningBot', logger)
logger.bot = pBotConfig;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runLearningBot -> Entering function."); }
let learningBot = TRADING_BOT_MODULE.newLearningBot(pBotConfig, logger);
learningBot.initialize(pProcessConfig, onInitializeReady);
function onInitializeReady(err) {
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
learningBot.run(whenRunFinishes);
function whenRunFinishes(err) {
pBotConfig.loopCounter = 0;
let botId;
botId = pBotConfig.dataMine + "." + pBotConfig.codeName + "." + pBotConfig.process;
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runLearningBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished sucessfully.");
logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runLearningBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
logger.persist();
} else {
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> whenStartFinishes -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> whenStartFinishes -> Execution will be stopped. ");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> whenStartFinishes -> Bye.");
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> whenStartFinishes -> Bot Id = " + botId);
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs.");
logger.persist();
}
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
} else {
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> err = " + err.message);
logger.write(MODULE_NAME, "[ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> Failed to initialize the bot. ");
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runLearningBot -> onInitializeReady -> err = " + err.message);
logger.persist();
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
}
catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> runLearningBot -> err = " + err.stack);
setTimeout(exitProcessInstance, WAIT_TIME_FOR_ALL_PROCESS_INSTANCES_TO_START)
}
}
}
catch (err) {
console.log(logDisplace + "Root : [ERROR] start -> bootingBot -> err = " + err.stack);
+16 -16
View File
@@ -13,10 +13,10 @@ exports.newSocialBots = function newSocialBots(bot, logger) {
return thisObject
function initialize() {
if (bot.SESSION.socialBots !== undefined) {
if (bot.SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
let socialBot = bot.SESSION.socialBots.bots[i]
if (bot.TRADING_SESSION.socialBots !== undefined) {
if (bot.TRADING_SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.TRADING_SESSION.socialBots.bots.length; i++) {
let socialBot = bot.TRADING_SESSION.socialBots.bots[i]
if (socialBot.type === "Telegram Bot") {
let config = socialBot.config
socialBot.botInstance = TELEGRAM_BOT_MODULE.newTelegramBot(bot, logger)
@@ -26,9 +26,9 @@ exports.newSocialBots = function newSocialBots(bot, logger) {
}
function announce(text) {
if (bot.SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
let socialBot = bot.SESSION.socialBots.bots[i]
if (bot.TRADING_SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.TRADING_SESSION.socialBots.bots.length; i++) {
let socialBot = bot.TRADING_SESSION.socialBots.bots[i]
try {
if (socialBot.type === "Telegram Bot") {
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, text).catch(err => logger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err))
@@ -40,15 +40,15 @@ exports.newSocialBots = function newSocialBots(bot, logger) {
}
}
bot.SESSION.socialBots.announce = announce
bot.TRADING_SESSION.socialBots.announce = announce
}
}
function finalize() {
if (bot.SESSION.socialBots === undefined) { return }
if (bot.SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
let socialBot = bot.SESSION.socialBots.bots[i]
if (bot.TRADING_SESSION.socialBots === undefined) { return }
if (bot.TRADING_SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.TRADING_SESSION.socialBots.bots.length; i++) {
let socialBot = bot.TRADING_SESSION.socialBots.bots[i]
if (socialBot.type === "Telegram Bot") {
socialBot.botInstance.finalize()
}
@@ -57,10 +57,10 @@ exports.newSocialBots = function newSocialBots(bot, logger) {
}
function sendMessage(message) {
if (bot.SESSION.socialBots !== undefined) {
if (bot.SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
let socialBot = bot.SESSION.socialBots.bots[i]
if (bot.TRADING_SESSION.socialBots !== undefined) {
if (bot.TRADING_SESSION.socialBots.bots !== undefined) {
for (let i = 0; i < bot.TRADING_SESSION.socialBots.bots.length; i++) {
let socialBot = bot.TRADING_SESSION.socialBots.bots[i]
if (socialBot.type === "Telegram Bot") {
socialBot.botInstance.sendMessage(message)
}
+7 -3
View File
@@ -100,8 +100,12 @@
}
}
if (bot.SESSION !== undefined && statusDependencyNode.bottype === "Trading Bot") {
sessionPath = bot.SESSION.folderName + "/"
if (bot.TRADING_SESSION !== undefined && statusDependencyNode.bottype === "Trading Bot") {
sessionPath = bot.TRADING_SESSION.folderName + "/"
}
if (bot.LEARNING_SESSION !== undefined && statusDependencyNode.bottype === "Learning Bot") {
sessionPath = bot.LEARNING_SESSION.folderName + "/"
}
/* Now we will see where do we need to fetch this status report from. */
@@ -264,7 +268,7 @@
On the contraty, if we are running a Sensor bot or an Indicator bot, we might, if necesary, use a previous version of a Status Report since
there will be no big impact, just some reprocessing.
*/
if (bot.SESSION !== undefined) {
if (bot.TRADING_SESSION !== undefined || bot.LEARNING_SESSION !== undefined) {
canUserPrevious = false
} else {
canUserPrevious = true
+1 -1
View File
@@ -23,7 +23,7 @@ exports.newTelegramBot = function newTelegramBot(bot, logger) {
thisObject.telegramBot = new Telegraf(botToken)
thisObject.telegramBot.start((ctx) => ctx.reply('Hi! I am the Telegram Bot that will tell you what happens with your trading session.'))
thisObject.telegramBot.help((ctx) => ctx.reply('I can stop the session if you type STOP.'))
thisObject.telegramBot.hears('STOP', (ctx) => bot.SESSION.stop(' by STOP command at Telegram.'))
thisObject.telegramBot.hears('STOP', (ctx) => bot.TRADING_SESSION.stop(' by STOP command at Telegram.'))
thisObject.telegramBot.launch()
const Telegram = require('telegraf/telegram')
+15 -15
View File
@@ -5,10 +5,10 @@
const TRADING_PROCESS_MODULE = require(global.ROOT_DIR + '/LowFrequencyTrading/TradingProcess.js');
const FILE_STORAGE = require('./FileStorage.js');
const SESSION = require(global.ROOT_DIR + 'Session');
const SESSION = require(global.ROOT_DIR + 'TradingSession');
let fileStorage = FILE_STORAGE.newFileStorage(parentLogger);
let session = SESSION.newSession(bot, parentLogger)
let session = SESSION.newTradingSession(bot, parentLogger)
const DEBUG_MODULE = require(global.ROOT_DIR + 'DebugLog');
let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble.
@@ -93,15 +93,15 @@
+ " Main Loop # " + pad(Number(bot.loopCounter), 8) + " " + bot.processNode.session.type + " " + bot.processNode.session.name)
/* Checking if we need to need to emit any event */
if (bot.SESSION_STATUS === 'Idle' && bot.STOP_SESSION === false) {
bot.SESSION_STATUS = 'Running'
if (bot.TRADING_SESSION_STATUS === 'Idle' && bot.STOP_SESSION === false) {
bot.TRADING_SESSION_STATUS = 'Running'
}
if (bot.SESSION_STATUS === 'Running' && bot.STOP_SESSION === true) {
bot.SESSION_STATUS = 'Stopped'
if (bot.TRADING_SESSION_STATUS === 'Running' && bot.STOP_SESSION === true) {
bot.TRADING_SESSION_STATUS = 'Stopped'
}
global.EMIT_SESSION_STATUS (bot.SESSION_STATUS, bot.sessionKey)
global.EMIT_SESSION_STATUS (bot.TRADING_SESSION_STATUS, bot.TRADING_SESSIONKey)
/* Checking if we should process this loop or not.*/
if (bot.STOP_SESSION === true) {
@@ -534,7 +534,7 @@
logger.persist();
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.sessionKey, 'Stopped')
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Stopped')
processStopped()
return;
}
@@ -560,17 +560,17 @@
if (processConfig.waitsForExecutionFinishedEvent === true) {
waitTime = 0
} else {
switch (bot.SESSION.type) {
switch (bot.TRADING_SESSION.type) {
case 'Live Trading Session': {
waitTime = bot.SESSION.parameters.timeFrame.config.value
waitTime = bot.TRADING_SESSION.parameters.timeFrame.config.value
break
}
case 'Fordward Tessting Session': {
waitTime = bot.SESSION.parameters.timeFrame.config.value
waitTime = bot.TRADING_SESSION.parameters.timeFrame.config.value
break
}
case 'Paper Trading Session': {
waitTime = bot.SESSION.parameters.timeFrame.config.value
waitTime = bot.TRADING_SESSION.parameters.timeFrame.config.value
break
}
case 'Backtesting Session': {
@@ -669,9 +669,9 @@
}
function sessionStopped() {
if (bot.SESSION_STATUS === 'Running') {
global.EVENT_SERVER_CLIENT.raiseEvent(bot.sessionKey, 'Stopped')
bot.SESSION_STATUS = 'Stopped'
if (bot.TRADING_SESSION_STATUS === 'Running') {
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Stopped')
bot.TRADING_SESSION_STATUS = 'Stopped'
}
}
+519
View File
@@ -0,0 +1,519 @@
exports.newTradingSession = function newTradingSession(bot, parentLogger) {
const MODULE_NAME = "Trading Session"
const FULL_LOG = true;
let thisObject = {
initialize: initialize
}
const SOCIAL_BOTS_MODULE = require('./SocialBots.js')
let socialBotsModule = SOCIAL_BOTS_MODULE.newSocialBots(bot, parentLogger)
return thisObject;
function initialize(pProcessConfig, callBackFunction) {
try {
/* Initialize this info so that everything is logged propeerly */
bot.TRADING_SESSION = {
name: bot.processNode.session.name,
id: bot.processNode.session.id
}
/* Set the folderName for early logging */
if (bot.processNode.session.config.folderName === undefined) {
bot.TRADING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.TRADING_SESSION.id
} else {
bot.TRADING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.processNode.session.config.folderName
}
/* Check if there is a session */
if (bot.processNode.session === undefined) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> Cannot run without a Session.");
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
return;
}
/* Listen to event to start or stop the session. */
bot.TRADING_SESSIONKey = bot.processNode.session.name + '-' + bot.processNode.session.type + '-' + bot.processNode.session.id
global.SESSION_MAP.set(bot.TRADING_SESSIONKey, bot.TRADING_SESSIONKey)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.TRADING_SESSIONKey, 'Trading Session Status', undefined, bot.TRADING_SESSIONKey, undefined, onSessionStatus)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.TRADING_SESSIONKey, 'Run Trading Session', undefined, bot.TRADING_SESSIONKey, undefined, onSessionRun)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.TRADING_SESSIONKey, 'Stop Trading Session', undefined, bot.TRADING_SESSIONKey, undefined, onSessionStop)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.TRADING_SESSIONKey, 'Resume Trading Session', undefined, bot.TRADING_SESSIONKey, undefined, onSessionResume)
/* Connect this here so that it is accesible from other places */
bot.TRADING_SESSIONError = sessionError
bot.TRADING_SESSIONWarning = sessionWarning
bot.TRADING_SESSIONInfo = sessionInfo
/* Heartbeats sent to the UI */
bot.TRADING_SESSIONHeartBeat = sessionHeartBeat
callBackFunction(global.DEFAULT_OK_RESPONSE)
return
function onSessionStatus() {
if (bot.TRADING_SESSION_STATUS === 'Running') {
let event = {
status: 'Trading Session Runnning'
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Status Response', event)
} else {
let event = {
status: 'Trading Session Not Runnning'
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Status Response', event)
}
}
function onSessionRun(message) {
try {
/* This happens when the UI is reloaded, the session was running and tries to run it again. */
if (bot.TRADING_SESSION_STATUS === 'Idle' || bot.TRADING_SESSION_STATUS === 'Running') {
parentLogger.write(MODULE_NAME, "[WARN] onSessionRun -> Event received to run the Session while it was already running. ")
return
}
/* We are going to run the Definition comming at the event. */
bot.TRADING_SYSTEM = JSON.parse(message.event.tradingSystem)
bot.TRADING_ENGINE = JSON.parse(message.event.tradingEngine)
bot.TRADING_SESSION = JSON.parse(message.event.session)
bot.DEPENDENCY_FILTER = JSON.parse(message.event.dependencyFilter)
bot.RESUME = false
bot.FIRST_EXECUTION = true
bot.TRADING_SESSION.stop = stopSession // stop function
setUpSessionFolderName()
/* We validate all parameters received and complete some that might be missing if needed. */
if (checkParemeters() === false) { return }
socialBotsModule.initialize()
let allGood
switch (bot.TRADING_SESSION.type) {
case 'Backtesting Session': {
allGood = startBackTesting(message)
break
}
case 'Live Trading Session': {
allGood = startLiveTrading(message)
break
}
case 'Fordward Testing Session': {
allGood = startFordwardTesting(message)
break
}
case 'Paper Trading Session': {
allGood = startPaperTrading(message)
break
}
}
if (allGood === true) {
bot.TRADING_SESSION_STATUS = 'Idle'
bot.STOP_SESSION = false
} else {
bot.STOP_SESSION = true
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] onSessionRun -> Stopping the Session now. ') }
}
socialBotsModule.sendMessage(bot.TRADING_SESSION.type + " '" + bot.TRADING_SESSION.name + "' is starting.")
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onSessionRun -> err = " + err.stack);
}
}
function onSessionStop() {
stopSession('Session Stopped From the User Interface.')
}
function onSessionResume(message) {
try {
if (bot.TRADING_SESSION.stop === undefined) {
parentLogger.write(MODULE_NAME, "[WARN] onSessionResume -> Event received to resume the Session that have never be ran before. ")
return
}
/* This happens when the UI is reloaded, the session was running and tries to run it again. */
if (bot.TRADING_SESSION_STATUS === 'Idle' || bot.TRADING_SESSION_STATUS === 'Running') {
parentLogger.write(MODULE_NAME, "[WARN] onSessionResume -> Event received to resume the Session while it was already running. ")
return
}
bot.RESUME = true
bot.STOP_SESSION = false
socialBotsModule.sendMessage(bot.TRADING_SESSION.type + " '" + bot.TRADING_SESSION.name + "' is resuming.")
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onSessionResume -> err = " + err.stack);
}
}
function stopSession(commandOrigin) {
socialBotsModule.sendMessage(bot.TRADING_SESSION.type + " '" + bot.TRADING_SESSION.name + "' is stopping " + commandOrigin)
socialBotsModule.finalize()
bot.STOP_SESSION = true
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] stopSession -> Stopping the Session now. ') }
sessionInfo(bot.TRADING_SESSION, commandOrigin)
}
function setUpSessionFolderName() {
/*
The session object is overwritten when the session is run. For that reason we
need to setup again the folder name at the Session level.
Set the folderName for logging, reports, context and data output
*/
let config
if (bot.TRADING_SESSION.config !== undefined) {
config = bot.TRADING_SESSION.config
if (config.folderName === undefined) {
bot.TRADING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.TRADING_SESSION.id
} else {
bot.TRADING_SESSION.folderName = bot.processNode.session.type.replace(' ', '-').replace(' ', '-') + '-' + bot.processNode.session.config.folderName
}
}
}
function checkParemeters() {
/*
Here we check all the Session Parameters received. If something critical is missing we abort returning false. If something
non critical is missing, we complete it with a default value.
*/
if (bot.TRADING_SESSION.parameters === undefined) {
let errorMessage = "Session Node with no Parameters."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION, errorMessage)
return false
}
/* Time Range */
if (bot.TRADING_SESSION.parameters.timeRange === undefined) { // if the Time Range is missing we create a default one.
bot.TRADING_SESSION.parameters.timeRange = {
name: 'Missing Time Range',
type: 'Time Range',
config: {
initialDatetime: (new Date()).valueOf(),
finalDatetime: (new Date()).valueOf() + global.ONE_YEAR_IN_MILISECONDS
}
}
} else {
/* Check that we received valid dates */
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
if (isNaN(new Date(bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime)).valueOf()) {
let errorMessage = "sessionParameters.timeRange.config.initialDatetime is not a valid date."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters, errorMessage)
return false
}
}
if (isNaN(new Date(bot.TRADING_SESSION.parameters.timeRange.config.finalDatetime)).valueOf()) {
let errorMessage = "sessionParameters.timeRange.config.initialDatetime is not a valid date."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters, errorMessage)
return false
}
}
/* Session Type Forced Values */
let today = (new Date()).valueOf()
let aYearAgo = today - global.ONE_YEAR_IN_MILISECONDS
let aYearFromNow = today + global.ONE_YEAR_IN_MILISECONDS
switch (bot.TRADING_SESSION.type) {
case 'Backtesting Session': {
useDefaultDatetimes(aYearAgo, today)
break
}
case 'Live Trading Session': {
useDefaultDatetimes(today, aYearFromNow)
break
}
case 'Fordward Testing Session': {
useDefaultDatetimes(today, aYearFromNow)
break
}
case 'Paper Trading Session': {
useDefaultDatetimes(today, aYearFromNow)
break
}
}
function useDefaultDatetimes(initialDefault, finalDefault) {
/*
Note that inside the system, we are going to deal with these
dates in their numeric value representation.
*/
/* Initial Datetime */
if (bot.TRADING_SESSION.type === 'Backtesting Session') {
if (bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime === undefined) {
bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime = initialDefault
} else {
bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime = (new Date(bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime)).valueOf()
}
} else {
/* Non backtest session can start from the past only if explicitly configured that way */
if (bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime === undefined || bot.TRADING_SESSION.parameters.timeRange.config.allowStartingFromThePast !== true) {
bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime = initialDefault
} else {
bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime = (new Date(bot.TRADING_SESSION.parameters.timeRange.config.initialDatetime)).valueOf()
}
}
/* Final Datetime */
if (bot.TRADING_SESSION.parameters.timeRange.config.finalDatetime === undefined) {
bot.TRADING_SESSION.parameters.timeRange.config.finalDatetime = finalDefault
} else {
bot.TRADING_SESSION.parameters.timeRange.config.finalDatetime = (new Date(bot.TRADING_SESSION.parameters.timeRange.config.finalDatetime)).valueOf()
}
}
/* Time Frame */
if (bot.TRADING_SESSION.parameters.timeFrame === undefined) {
let errorMessage = "Session Parameters Node with no Time Frame."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters, errorMessage)
return false
}
if (bot.TRADING_SESSION.parameters.timeFrame.config.label === undefined) {
let errorMessage = "Session Parameters Node with no Time Frame Label configuration."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters.timeFrame, errorMessage)
return false
}
bot.TRADING_SESSION.parameters.timeFrame.config.value = getTimeFrameFromLabel(bot.TRADING_SESSION.parameters.timeFrame.config.label)
if (bot.TRADING_SESSION.parameters.timeFrame.config.value === undefined) {
let errorMessage = "Config error: label value not recognized. Try 01-min or 01-hs for example."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters.timeFrame, errorMessage)
return false
}
/* Session Base Asset */
if (bot.TRADING_SESSION.parameters.sessionBaseAsset === undefined) {
let errorMessage = "Session Parameters Node with no Session Base Asset."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters, errorMessage)
return false
}
if (bot.TRADING_SESSION.parameters.sessionBaseAsset.config.initialBalance === undefined) {
let errorMessage = "Session Parameters Session Base Asset with no initialBalance configuration."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters.sessionBaseAsset, errorMessage)
return false
}
/* Session Quoted Asset */
if (bot.TRADING_SESSION.parameters.sessionQuotedAsset === undefined) {
let errorMessage = "Session Parameters Node with no Session Quoted Asset."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters, errorMessage)
return false
}
if (bot.TRADING_SESSION.parameters.sessionQuotedAsset.config.initialBalance === undefined) {
let errorMessage = "Session Parameters Session Quoted Asset with no initialBalance configuration."
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> checkParemeters -> " + errorMessage)
bot.TRADING_SESSIONError(bot.TRADING_SESSION.parameters.sessionQuotedAsset, errorMessage)
return false
}
/* Slippage */
if (bot.TRADING_SESSION.parameters.slippage === undefined) { // if the Slippage is missing we create a default one.
bot.TRADING_SESSION.parameters.slippage = {
name: 'Missing Slippage',
type: 'Slippage',
config: {
marketOrderRate: 0,
stopLoss: 0,
takeProfit: 0
}
}
}
if (bot.TRADING_SESSION.parameters.slippage.config.marketOrderRate === undefined) { // if the marketOrderRate is missing we create a default one.
bot.TRADING_SESSION.parameters.slippage.config.marketOrderRate = 0
}
if (bot.TRADING_SESSION.parameters.slippage.config.stopLoss === undefined) { // if the stopLoss is missing we create a default one.
bot.TRADING_SESSION.parameters.slippage.config.stopLoss = 0
}
if (bot.TRADING_SESSION.parameters.slippage.config.takeProfit === undefined) { // if the takeProfit is missing we create a default one.
bot.TRADING_SESSION.parameters.slippage.config.takeProfit = 0
}
/* Fee Structure */
if (bot.TRADING_SESSION.parameters.feeStructure === undefined) { // if the Fee Structure is missing we create a default one.
bot.TRADING_SESSION.parameters.feeStructure = {
name: 'Missing Fee Structure',
type: 'Fee Structure',
config: {
maker: 0,
taker: 0
}
}
}
if (bot.TRADING_SESSION.parameters.feeStructure.config.maker === undefined) { // if the maker is missing we create a default one.
bot.TRADING_SESSION.parameters.feeStructure.config.maker = 0
}
if (bot.TRADING_SESSION.parameters.feeStructure.config.taker === undefined) { // if the taker is missing we create a default one.
bot.TRADING_SESSION.parameters.feeStructure.config.taker = 0
}
return true
}
function startBackTesting(message) {
return true
}
function startLiveTrading(message) {
if (bot.KEY === undefined || bot.SECRET === undefined) {
let errorMessage = "Key 'codeName' or 'secret' not provided. Plese check that and try again."
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[ERROR] initialize -> startLiveTrading -> " + errorMessage); }
bot.TRADING_SESSIONError(bot.TRADING_SESSION, errorMessage)
return false
}
return true
}
function startFordwardTesting(message) {
if (bot.KEY === undefined || bot.SECRET === undefined) {
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[WARN] initialize -> startFordwardTesting -> Key name or Secret not provided, not possible to run the process in Forward Testing mode."); }
console.log("Key 'codeName' or 'secret' not provided. Plese check that and try again.")
return false
}
/* Reduce the balance */
let balancePercentage = 1 // This is the default value
if (bot.TRADING_SESSION.config.balancePercentage !== undefined) {
balancePercentage = bot.TRADING_SESSION.config.balancePercentage
}
bot.TRADING_SESSION.parameters.sessionBaseAsset.config.initialBalance = bot.TRADING_SESSION.parameters.sessionBaseAsset.config.initialBalance * balancePercentage / 100
bot.TRADING_SESSION.parameters.sessionQuotedAsset.config.initialBalance = bot.TRADING_SESSION.parameters.sessionQuotedAsset.config.initialBalance * balancePercentage / 100
bot.TRADING_SESSION.parameters.sessionBaseAsset.config.minimumBalance = bot.TRADING_SESSION.parameters.sessionBaseAsset.config.minimumBalance * balancePercentage / 100
bot.TRADING_SESSION.parameters.sessionQuotedAsset.config.minimumBalance = bot.TRADING_SESSION.parameters.sessionQuotedAsset.config.minimumBalance * balancePercentage / 100
bot.TRADING_SESSION.parameters.sessionBaseAsset.config.maximumBalance = bot.TRADING_SESSION.parameters.sessionBaseAsset.config.maximumBalance * balancePercentage / 100
bot.TRADING_SESSION.parameters.sessionQuotedAsset.config.maximumBalance = bot.TRADING_SESSION.parameters.sessionQuotedAsset.config.maximumBalance * balancePercentage / 100
pProcessConfig.normalWaitTime = bot.TRADING_SESSION.parameters.timeFrame.config.value
return true
}
function startPaperTrading(message) {
return true
}
function getTimeFrameFromLabel(timeFrameLabel) {
for (let i = 0; i < global.marketFilesPeriods.length; i++) {
let value = global.marketFilesPeriods[i][0]
let label = global.marketFilesPeriods[i][1]
if (timeFrameLabel === label) {
return value
}
}
for (let i = 0; i < global.dailyFilePeriods.length; i++) {
let value = global.dailyFilePeriods[i][0]
let label = global.dailyFilePeriods[i][1]
if (timeFrameLabel === label) {
return value
}
}
}
function sessionHeartBeat(processingDate, percentage, status) {
let event = {
seconds: (new Date()).getSeconds(),
processingDate: processingDate,
percentage: percentage,
status: status
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Heartbeat', event)
if (global.STOP_TASK_GRACEFULLY === true) {
bot.STOP_SESSION = true
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] sessionHeartBeat -> Stopping the Session now. ') }
}
}
function sessionError(node, errorMessage) {
let event
if (node !== undefined) {
event = {
nodeName: node.name,
nodeType: node.type,
nodeId: node.id,
errorMessage: errorMessage
}
} else {
event = {
errorMessage: errorMessage
}
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Error', event)
if (global.STOP_TASK_GRACEFULLY === true) {
bot.STOP_SESSION = true
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] sessionError -> Stopping the Session now. ') }
}
}
function sessionWarning(node, warningMessage) {
let event
if (node !== undefined) {
event = {
nodeName: node.name,
nodeType: node.type,
nodeId: node.id,
warningMessage: warningMessage
}
} else {
event = {
warningMessage: warningMessage
}
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Warning', event)
if (global.STOP_TASK_GRACEFULLY === true) {
bot.STOP_SESSION = true
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] sessionWarning -> Stopping the Session now. ') }
}
}
function sessionInfo(node, infoMessage) {
let event
if (node !== undefined) {
event = {
nodeName: node.name,
nodeType: node.type,
nodeId: node.id,
infoMessage: infoMessage
}
} else {
event = {
infoMessage: infoMessage
}
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.TRADING_SESSIONKey, 'Info', event)
if (global.STOP_TASK_GRACEFULLY === true) {
bot.STOP_SESSION = true
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, '[IMPORTANT] sessionInfo -> Stopping the Session now. ') }
}
}
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
};
+2 -2
View File
@@ -30,8 +30,8 @@ global.ROOT_DIR = './';
global.ONE_YEAR_IN_MILISECONDS = 365 * 24 * 60 * 60 * 1000
global.ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000
global.ONE_MIN_IN_MILISECONDS = 60 * 1000
global.LOGGER_MAP = new Map()
global.SESSION_MAP = new Map()
global.LOGGER_MAP = new Map() // We will put all the loggers in a map, so that we can eventually finalize them.
global.SESSION_MAP = new Map() // We will put all the sessions in a map, so that we can eventually finalize them.
global.UNIQUE_ID = function () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {