Compare commits

..
Author SHA1 Message Date
Luis Fernando Molina 9c7428ad36 Merge pull request #216 from Superalgos/develop
Beta 4
2020-05-03 15:45:18 +02:00
Luis Fernando Molina e37b09ede6 Version Beta 4 2020-05-03 15:44:32 +02:00
Luis Fernando Molina 1f3f8e0325 Bug fixed 2020-05-02 10:16:21 +02:00
Luis Fernando Molina d5847c1ede Bug fixed 2020-05-01 16:32:39 +02:00
Luis Fernando Molina f9300a2d87 Update CONTRIBUTING.md 2020-05-01 10:06:44 +02:00
Luis Fernando Molina 879aefcfea conditions editor 2020-04-30 18:11:54 +02:00
Luis Fernando Molina ec6e9fc907 Bug fixes that improve resilience when running live 2020-04-27 10:13:52 +02:00
Luis Fernando Molina 9fb3241fe5 Update README.md 2020-04-26 17:16:26 +02:00
Luis Fernando Molina 7cd9727bab Update DataDependencies.js 2020-04-25 11:50:21 +02:00
Luis Fernando Molina 2b3f8a6e5f final bug fixed 2020-04-25 10:39:49 +02:00
Luis Fernando Molina 1decce05cf Final Bug Fixed 2020-04-25 10:13:54 +02:00
Luis Fernando Molina 123ea66eeb Bugs Fixed 2020-04-25 09:08:30 +02:00
Luis Fernando Molina 37dd81a551 Update StatusReport.js 2020-04-24 17:43:46 +02:00
Luis Fernando Molina 948bf6c75e Update StatusReport.js 2020-04-24 17:40:38 +02:00
Luis Fernando Molina d95ce8e48a Update StatusReport.js 2020-04-24 17:34:50 +02:00
Luis Fernando Molina 5aed29bd4c Bugs fixed 2020-04-24 16:31:46 +02:00
Luis Fernando Molina 0791d4e2f0 bug fixed 2020-04-24 15:50:49 +02:00
Luis Fernando Molina 4604a14326 Update ProcessExecutionEvents.js 2020-04-24 15:25:24 +02:00
Luis Fernando Molina 2fa549015b Update AppSchema.json 2020-04-24 15:06:49 +02:00
Luis Fernando Molina a3efd3eaf0 Home Network fully implemented 2020-04-24 13:40:42 +02:00
Luis Fernando Molina 2ed86e0118 Remote Backends 2020-04-22 14:41:23 +02:00
60 changed files with 2020 additions and 449 deletions

No files matched your search

+27 -36
View File
@@ -810,7 +810,7 @@
"disableIfPropertyIsDefined": true,
"propertyToCheckFor": "javascriptCode",
"label": "Add Code",
"relatedUiObject": "Javascript Code",
"relatedUiObject": "Condition",
"actionFunction": "payload.onMenuItemClick"
},
{
@@ -1245,7 +1245,7 @@
"config": true
},
"initialValues": {
"code": "{ \n\"ipAddress\": \"\", \n\"webPort\": \"\", \n\"webSocketsPort\": \"\"\n}"
"code": "{ \n\"host\": \"localhost\", \n\"webPort\": \"34247\", \n\"webSocketsPort\": \"8080\"\n}"
},
"isTitleAllwaysVisible": true,
"addLeftIcons": true,
@@ -1322,7 +1322,6 @@
"actionFunction": "payload.onMenuItemClick"
}
],
"isTitleAllwaysVisible": true,
"addLeftIcons": true,
"level": 1,
"chainAttachesTo": {
@@ -1360,6 +1359,16 @@
"iconPathOff": "paper-plane",
"actionFunction": "payload.onMenuItemClick"
},
{
"action": "Debug Task",
"label": "Debug",
"workingLabel": "Debugging",
"workDoneLabel": "Debug Request Sent",
"workFailedLabel": "Task Cannot be Debugged",
"iconPathOn": "status-dependency",
"iconPathOff": "status-dependency",
"actionFunction": "payload.onMenuItemClick"
},
{
"action": "Add UI Object",
"disableIfPropertyIsDefined": true,
@@ -2208,7 +2217,7 @@
"compatibleTypes": "->Trading System->"
},
"chainAttachesTo": {
"compatibleTypes": "->Process Instance->"
"compatibleTypes": "->Trading Process Instance->"
},
"icon": "session-paper-trading",
"properties": [
@@ -2293,7 +2302,7 @@
"compatibleTypes": "->Trading System->"
},
"chainAttachesTo": {
"compatibleTypes": "->Process Instance->"
"compatibleTypes": "->Trading Process Instance->"
},
"icon": "session-forward-testing",
"properties": [
@@ -2403,7 +2412,7 @@
"compatibleTypes": "->Trading System->"
},
"chainAttachesTo": {
"compatibleTypes": "->Process Instance->"
"compatibleTypes": "->Trading Process Instance->"
},
"icon": "session-live-trading",
"properties": [
@@ -4011,12 +4020,14 @@
{
"name": "positionSize",
"type": "node",
"childType": "Position Size"
"childType": "Position Size",
"autoAdd": true
},
{
"name": "positionRate",
"type": "node",
"childType": "Position Rate"
"childType": "Position Rate",
"autoAdd": true
}
],
"propertyNameAtParent": "initialDefinition"
@@ -4370,7 +4381,8 @@
{
"name": "formula",
"type": "node",
"childType": "Formula"
"childType": "Formula",
"autoAdd": true
}
],
"propertyNameAtParent": "positionSize"
@@ -4407,7 +4419,8 @@
{
"name": "formula",
"type": "node",
"childType": "Formula"
"childType": "Formula",
"autoAdd": true
}
],
"propertyNameAtParent": "positionRate"
@@ -4809,7 +4822,7 @@
{
"action": "Send Webhook Test Message",
"label": "Send Test Message",
"workingLabel": "Seinding Message",
"workingLabel": "Sending Message",
"workDoneLabel": "Message Sent",
"workFailedLabel": "Message not Delived",
"iconPathOn": "paper-plane",
@@ -6095,7 +6108,7 @@
"compatibleTypes": "->Crypto Exchange->"
},
"chainAttachesTo": {
"compatibleTypes": "->Data Mining->Testing Environmnet->Production Environment->Template Structure->"
"compatibleTypes": "->Data Mining->Testing Environment->Production Environment->Template Structure->"
},
"alternativeIcons": "Use Reference Parent",
"title": [
@@ -6164,7 +6177,6 @@
"name": "exchangeTasks",
"type": "array",
"childType": "Exchange Tasks",
"autoAdd": true,
"monitorChildrenRunning": true
}
]
@@ -6217,17 +6229,10 @@
},
"propertyNameAtParent": "testingEnvironment",
"properties": [
{
"name": "taskManagers",
"type": "array",
"childType": "Task Manager",
"autoAdd": true
},
{
"name": "exchangeTasks",
"type": "array",
"childType": "Exchange Tasks",
"autoAdd": true,
"monitorChildrenRunning": true
}
]
@@ -6280,17 +6285,10 @@
},
"propertyNameAtParent": "productionEnvironment",
"properties": [
{
"name": "taskManagers",
"type": "array",
"childType": "Task Manager",
"autoAdd": true
},
{
"name": "exchangeTasks",
"type": "array",
"childType": "Exchange Tasks",
"autoAdd": true,
"monitorChildrenRunning": true
}
]
@@ -6403,7 +6401,7 @@
"compatibleTypes": "->Crypto Exchange->"
},
"chainAttachesTo": {
"compatibleTypes": "->Data Storage->"
"compatibleTypes": "->Session Based Data->"
},
"propertyNameAtParent": "exchangeSessions",
"properties": [
@@ -6442,17 +6440,10 @@
},
"propertyNameAtParent": "sessionBasedData",
"properties": [
{
"name": "sessionReferences",
"type": "array",
"childType": "Session Reference",
"autoAdd": true
},
{
"name": "exchangeSessions",
"type": "array",
"childType": "Exchange Sessions",
"autoAdd": true
"childType": "Exchange Sessions"
}
]
},
+1
View File
@@ -94,6 +94,7 @@ function newAppLoader() {
'FloatingSpace/ConfigEditor.js',
'FloatingSpace/ConditionEditor.js',
'FloatingSpace/FormulaEditor.js',
'FloatingSpace/Picker.js',
'Scales/RateScale.js',
'Scales/TimeScale.js',
+6 -6
View File
@@ -51,17 +51,17 @@
//console.log('[INFO] BackendServers -> Task Manager Server -> runTask -> Entering function.')
if (message.event === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without Event -> message = ' + JSON.stringify(message))
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without Event -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
if (message.event.taskId === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without taskId -> message = ' + JSON.stringify(message))
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without taskId -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
if (message.event.definition === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without Definition -> message = ' + JSON.stringify(message))
if (message.event.taskDefinition === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without taskDefinition -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
@@ -116,12 +116,12 @@
//console.log('[INFO] BackendServers -> Task Manager Server -> stopTask -> Entering function.')
if (message.event === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> stopTask -> Message Received Without Event -> message = ' + JSON.stringify(message))
console.log('[WARN] BackendServers -> Task Manager Server -> stopTask -> Message Received Without Event -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
if (message.event.taskId === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> stopTask -> Message Received Without taskId -> message = ' + JSON.stringify(message))
console.log('[WARN] BackendServers -> Task Manager Server -> stopTask -> Message Received Without taskId -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
+5 -5
View File
@@ -47,7 +47,7 @@
try {
if (LOG_INFO === true) {
console.log('Message Received: ' + message)
console.log('Message Received: ' + message.substring(0, 1000))
}
let messageArray = message.split('|*|')
@@ -58,7 +58,7 @@
if (origin === 'Web Browser') {
if (isNaN(nonce) || nonce === "") {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce is not a Number. message = ' + message)
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce is not a Number. message = ' + message.substring(0, 1000))
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce is not a Number. nonce = ' + nonce)
return
}
@@ -68,7 +68,7 @@
}
if (Number(nonce) < Number(lastNonce)) {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. message = ' + message)
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. message = ' + message.substring(0, 1000))
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. nonce = ' + nonce)
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. lastNonce = ' + lastNonce)
return
@@ -79,7 +79,7 @@
try {
let jsonCheck = JSON.parse(messageToEventServer)
} catch (err) {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Message received from the browser is not a valid JSON. message = ' + message)
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Message received from the browser is not a valid JSON. message = ' + message.substring(0, 1000))
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Message received from the browser is not a valid JSON. messageToEventServer = ' + messageToEventServer)
return
}
@@ -106,7 +106,7 @@
console.log('Web Sockets Server Started.')
} catch (err) {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> err.message = ' + err.message)
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> err.message = ' + err.message.substring(0, 1000))
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ We are thrilled you are interested in contributing to this project. Your help ma
Superalgos is a collective project, currently at a very early stage. We not only welcome contributions but may even choose to incentivize relevant contributions via the project's native crypto token, to be deployed in the near future.
Please read the [Join the Dev Team]( https://superalgos.org/developers-join-dev-team.shtml) page in our website to learn more about how you may become a relevant member of the Superalgos Project and even make a living of contributing code.
Contributions are deemed _voluntary work_, irrespective of the incentives that may be in place, and are subject to the conditions described in the software [LICENSE](LICENSE).
-2
View File
@@ -130,8 +130,6 @@ function newCanvas () {
animation.initialize()
thisObject.animation = animation
/* Low Level Infraestructure First */
animation.addCallBackFunction('System Event Handler Physics', eventsServerClient.physics)
/* Spcaces Physics */
animation.addCallBackFunction('CockpitSpace Physics', thisObject.cockpitSpace.physics)
@@ -146,6 +146,13 @@ function newPlottersManager () {
}
}
let host = layer.networkNode.code.host
let webPort = layer.networkNode.code.webPort
if (host === undefined) { host = 'localhost' }
if (webPort === undefined) { webPort = window.location.port }
let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(layer.networkNode.id)
storage.initialize(
dataMine,
bot,
@@ -155,6 +162,9 @@ function newPlottersManager () {
market,
datetime,
timeFrame,
host,
webPort,
eventsServerClient,
onProductStorageInitialized
)
@@ -24,23 +24,19 @@ function newProtocolNode () {
/* Children Nodes */
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 (node[property.name] !== undefined) {
if (property.name !== previousPropertyName) {
if (lightingPath === undefined) {
object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseCode, includeIds, includeReferencesInSavedPayload, includePayload)
} else {
let newLightingPath = getNewLightingPath(lightingPath, node.type, property.childType)
if (newLightingPath !== undefined) {
object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseCode, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath)
}
if (lightingPath === undefined) {
object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseCode, includeIds, includeReferencesInSavedPayload, includePayload)
} else {
let newLightingPath = getNewLightingPath(lightingPath, node.type, property.childType)
if (newLightingPath !== undefined) {
object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseCode, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath)
}
previousPropertyName = property.name
}
}
break
@@ -7,26 +7,15 @@ function newSessionFunctions () {
return thisObject
function runSession (node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, callBackFunction) {
/* We can not run a sessionif its parent process is not running. Less if it does not have a parent. */
if (node.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be able to run.')
if (validations(node) !== true) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
if (node.payload.parentNode.payload.uiObject.isRunning !== true) {
node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be running to be able to run.')
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode
let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id)
if (node.payload.referenceParent === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to reference a Trading System.')
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
node.payload.uiObject.run(callBackFunction)
node.payload.uiObject.run(eventsServerClient, callBackFunction)
let key = node.name + '-' + node.type + '-' + node.id
@@ -77,9 +66,65 @@ function newSessionFunctions () {
}
function stopSession (node, functionLibraryProtocolNode, callBackFunction) {
if (validations(node) !== true) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode
let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id)
let key = node.name + '-' + node.type + '-' + node.id
eventsServerClient.raiseEvent(key, 'Stop 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 Trading Process Instance.')
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
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside Exchange Tasks.')
return
}
if (node.payload.parentNode.payload.parentNode.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 (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to be inside a Network Node.')
return
}
if (node.payload.parentNode.payload.uiObject.isRunning !== true) {
node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be running.')
return
}
if (node.payload.referenceParent === undefined) {
node.payload.uiObject.setErrorMessage('Session needs to reference a Trading System.')
return
}
return true
}
}
@@ -12,23 +12,21 @@ function newTaskFunctions () {
return thisObject
function runTask (node, functionLibraryProtocolNode, callBackFunction) {
/* Check if it is possible to Run or not */
if (node.bot === undefined) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
if (node.bot.processes.length === 0) {
function runTask (node, functionLibraryProtocolNode, isDebugging, callBackFunction) {
if (validations(node) !== true) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode
let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id)
for (let i = 0; i < node.bot.processes.length; i++) {
let process = node.bot.processes[i]
process.payload.uiObject.run()
process.payload.uiObject.run(eventsServerClient)
}
let lightingPath = '->Task->' +
let taskLightingPath = '->Task->' +
'Sensor Bot Instance->' +
'Indicator Bot Instance->' +
'Trading Bot Instance->' +
@@ -58,25 +56,48 @@ function newTaskFunctions () {
'Trading Bot->' +
'Data Mine->'
let definition = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
let taskDefinition = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, taskLightingPath)
let networkLightingPath = '->Network->Network Node->' +
'Data Storage->Session Independent Data->Exchange Data Products->' +
'Single Market Data->Data Product->Product Definition->' +
'Data Mining->Testing Environment->Production Environment->' +
'Exchange Tasks->Crypto Exchange->' +
'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->' +
'Market Reference->Market->' +
'Process Definition->'
let networkDefinition = functionLibraryProtocolNode.getProtocolNode(networkNode.payload.parentNode, false, true, true, false, false, networkLightingPath)
let event = {
taskId: node.id,
taskName: node.name,
definition: JSON.stringify(definition) // <- We need to do this workaround in order no to send unescaped charactars to the taskManager.
taskDefinition: JSON.stringify(taskDefinition),
networkDefinition: JSON.stringify(networkDefinition)
}
if (node.payload.parentNode === undefined) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
if (isDebugging === true) {
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
eventsServerClient.raiseEvent('Task Server', 'Debug Task Started', event)
return
}
node.payload.uiObject.run(callBackFunction)
node.payload.uiObject.run(eventsServerClient, callBackFunction)
eventsServerClient.raiseEvent('Task Manager', 'Run Task', event)
}
function stopTask (node, functionLibraryProtocolNode, callBackFunction) {
if (validations(node) !== true) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode
let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id)
let event = {
taskId: node.id,
taskName: node.name
@@ -94,6 +115,60 @@ function newTaskFunctions () {
}
}
function validations (node) {
if (node.bot === undefined) {
node.payload.uiObject.setErrorMessage('Task needs to have a Bot Instance.')
return
}
if (node.bot.processes.length === 0) {
node.payload.uiObject.setErrorMessage('Task Bot Instance needs to have al least once Process Instance.')
return
}
if (node.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Task needs to be inside a Task Manager.')
return
}
if (node.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Task needs to be inside Exchange Tasks.')
return
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Task needs to be inside a Testing or Production Environment or a Data Mining node.')
return
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Task needs to be inside a Network Node.')
return
}
if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
node.payload.uiObject.setErrorMessage('Task needs to be inside a Network.')
return
}
let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode
if (loadPropertyFromNodeConfig(networkNode.payload, 'host') === undefined) {
node.payload.uiObject.setErrorMessage('Network Node needs to have a valid Host property at its config.')
return
}
if (loadPropertyFromNodeConfig(networkNode.payload, 'webPort') === undefined) {
node.payload.uiObject.setErrorMessage('Network Node needs to have a valid webPort property at its config.')
return
}
if (loadPropertyFromNodeConfig(networkNode.payload, 'webSocketsPort') === undefined) {
node.payload.uiObject.setErrorMessage('Network Node needs to have a valid webSocketsPort property at its config.')
return
}
return true
}
function runAllTasks (taskManager, functionLibraryProtocolNode) {
for (let i = 0; i < taskManager.tasks.length; i++) {
let node = taskManager.tasks[i]
@@ -37,7 +37,7 @@ function newUiObjectsFromNodes () {
for (let i = 0; i < includeDataMines.length; i++) {
let name = includeDataMines[i]
blobService.getBlobToText('DataMines' + '/' + name, undefined, onFileReceived, true)
blobService.getFileFromHost('DataMines' + '/' + name, onFileReceived, true)
function onFileReceived (err, text, response) {
if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
console.log('Cannot load included Data Mine ' + name + '. The workspace can not be loaded.')
@@ -66,7 +66,7 @@ function newUiObjectsFromNodes () {
for (let i = 0; i < includeTradingSystems.length; i++) {
let name = includeTradingSystems[i]
blobService.getBlobToText('TradingSystems' + '/' + name, undefined, onFileReceived, true)
blobService.getFileFromHost('TradingSystems' + '/' + name, onFileReceived, true)
function onFileReceived (err, text, response) {
if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
console.log('Cannot load included Data Mine ' + name + '. The workspace can not be loaded.')
@@ -95,7 +95,7 @@ function newUiObjectsFromNodes () {
for (let i = 0; i < includeSuperScripts.length; i++) {
let name = includeSuperScripts[i]
blobService.getBlobToText('SuperScripts' + '/' + name, undefined, onFileReceived, true)
blobService.getFileFromHost('SuperScripts' + '/' + name, onFileReceived, true)
function onFileReceived (err, text, response) {
if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
console.log('Cannot load included Data Mine ' + name + '. The workspace can not be loaded.')
+65 -1
View File
@@ -10,6 +10,7 @@ function newWorkspace () {
container: undefined,
enabled: false,
nodeChildren: undefined,
eventsServerClients: new Map(),
save: saveWorkspace,
getHierarchyHeads: getHierarchyHeads,
getNodeThatIsOnFocus: getNodeThatIsOnFocus,
@@ -93,6 +94,7 @@ function newWorkspace () {
thisObject.workspaceNode = JSON.parse(savedWorkspace)
}
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode)
setupEventsServerClients()
thisObject.enabled = true
setInterval(saveWorkspace, 60000)
@@ -101,6 +103,38 @@ function newWorkspace () {
}
}
function setupEventsServerClients () {
for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) {
let rootNode = thisObject.workspaceNode.rootNodes[i]
if (rootNode.type === 'Network') {
for (let j = 0; j < rootNode.networkNodes.length; j++) {
let networkNode = rootNode.networkNodes[j]
let host
let webSocketsPort
/* At this point the node does not have the payload property yet, that is why we have to do this manually */
try {
let code = JSON.parse(networkNode.code)
host = code.host
webSocketsPort = code.webSocketsPort
} catch (err) {
console.log('[ERROR] networkNode ' + networkNode.name + ' has an invalid configuration. Cannot know the host name and webSocketsPort.')
return
}
if (host === undefined) { host = 'localhost' }
if (webSocketsPort === undefined) { webSocketsPort = '8080' }
let eventsServerClient = newEventsServerClient(host, webSocketsPort, networkNode.name)
eventsServerClient.initialize()
thisObject.eventsServerClients.set(networkNode.id, eventsServerClient)
}
}
}
}
function chainDetachNode (node) {
functionLibraryChainAttachDetach.chainDetachNode(node, thisObject.workspaceNode.rootNodes)
}
@@ -118,6 +152,17 @@ function newWorkspace () {
}
function saveWorkspace () {
/* When there is an exception while loading the app, the rootNodes of the workspace get into null value. To avoid saving a corrupt staate we are going to verufy we are not in that situation before saving. */
let workspace = canvas.designSpace.workspace.workspaceNode
for (let i = 0; i < workspace.rootNodes.length; i++) {
let rootNode = workspace.rootNodes[i]
if (rootNode === null) {
canvas.cockpitSpace.setStatus('Could not save the Workspace. The state of the workspace in memory is corrupt, please reload the App.', 150, canvas.cockpitSpace.statusTypes.WARNING)
return
}
}
let savedSessionTimestamp = window.localStorage.getItem('Session Timestamp')
if (Number(savedSessionTimestamp) !== sessionTimestamp) {
canvas.cockpitSpace.setStatus('Could not save the Workspace. You have more that one instance of the Superlagos User Interface open at the same time. Plese close this instance as it is older than the others.', 150, canvas.cockpitSpace.statusTypes.WARNING)
@@ -130,6 +175,19 @@ function newWorkspace () {
}
function physics () {
eventsServerClientsPhysics()
replacingWorkspacePhysics()
}
function eventsServerClientsPhysics () {
thisObject.eventsServerClients.forEach(applyPhysics)
function applyPhysics (eventServerClient) {
eventServerClient.physics()
}
}
function replacingWorkspacePhysics () {
if (thisObject.enabled !== true) { return }
if (workingAtTask > 0) {
@@ -151,6 +209,7 @@ function newWorkspace () {
break
case 4:
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, true)
setupEventsServerClients()
workingAtTask++
break
case 5:
@@ -358,10 +417,15 @@ function newWorkspace () {
downloadText(fileName, text)
}
break
case 'Debug Task':
{
functionLibraryTaskFunctions.runTask(payload.node, functionLibraryProtocolNode, true, callBackFunction)
}
break
case 'Run Task':
{
functionLibraryTaskFunctions.runTask(payload.node, functionLibraryProtocolNode, callBackFunction)
functionLibraryTaskFunctions.runTask(payload.node, functionLibraryProtocolNode, false, callBackFunction)
}
break
case 'Stop Task':
+13 -10
View File
@@ -1,5 +1,5 @@
function newEventsServerClient () {
function newEventsServerClient (host, port, hostName) {
/* Web Sockets Connection */
const MODULE_NAME = 'System Event Handler'
@@ -8,7 +8,10 @@ function newEventsServerClient () {
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
const WEB_SOCKETS_URL = 'ws://localhost:8080'
if (host === '' || host === undefined) { host = 'localhost' }
if (port === '' || port === undefined) { port = '8080' }
const WEB_SOCKETS_URL = 'ws://' + host + ':' + port + ''
let WEB_SOCKETS_CONNECTION
let thisObject = {
@@ -56,12 +59,7 @@ function newEventsServerClient () {
responseWaiters.set(command.callerId, responseCallBack)
}
if (WEB_SOCKETS_CONNECTION.readyState === 1) {
// 1 means connected and ready.
sendToWebSocketServer(command)
} else {
console.log('WebSocket message could not be sent because the connection was not ready. Message = ' + JSON.stringify(command))
}
sendToWebSocketServer(command)
}
function sendToWebSocketServer (command) {
@@ -72,7 +70,12 @@ function newEventsServerClient () {
commandsSentByTimestamp.set(stringNonce, timestamp)
let messageToWebSocketServer = 'Web Browser' + '|*|' + stringNonce + '|*|' + JSON.stringify(command)
WEB_SOCKETS_CONNECTION.send(messageToWebSocketServer)
if (WEB_SOCKETS_CONNECTION.readyState === 1) {
WEB_SOCKETS_CONNECTION.send(messageToWebSocketServer)
} else {
console.log('WebSocket message could not be sent because the connection was not ready. Will retry soon. Message = ' + JSON.stringify(command))
}
}
function createEventHandler (eventHandlerName, callerId, responseCallBack) {
@@ -153,7 +156,7 @@ function newEventsServerClient () {
}
if (thisObject.isConnected() !== true) {
canvas.cockpitSpace.setStatus('Connection with the local backend lost. Please check that all localhost servers are running.', 100, canvas.cockpitSpace.statusTypes.WARNING)
canvas.cockpitSpace.setStatus('Connecting to ' + hostName + ' Network Node. Please wait until the connection is established.', 100, canvas.cockpitSpace.statusTypes.WARNING)
} else {
retryCommandsPhysics()
}
+15 -7
View File
@@ -22,27 +22,35 @@ function newCircularProgressBar () {
thisObject.container.frame.position.y = 0
let opacityCounters = []
let eventSubscriptionIdHeartbeat
let needToDrawRing = true
let eventsServerClient
return thisObject
function finalize () {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
if (eventSubscriptionIdHeartbeat !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdHeartbeat)
}
finalizeEventsServerClient()
thisObject.container = undefined
thisObject.payload = undefined
thisObject.fitFunction = undefined
}
function initialize (payload) {
function finalizeEventsServerClient () {
if (eventsServerClient !== undefined) {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
if (eventSubscriptionIdHeartbeat !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdHeartbeat)
}
}
}
function initialize (payload, pEventsServerClient) {
thisObject.payload = payload
finalizeEventsServerClient()
eventsServerClient = pEventsServerClient
for (let i = 0; i < 60; i++) {
opacityCounters.push(0)
}
-19
View File
@@ -4,8 +4,6 @@ function newCodeEditor () {
let thisObject = {
isVisibleFunction: undefined,
iconOK: undefined,
iconNOT_OK: undefined,
visible: false,
imagePathOK: undefined,
imagePathNOT_OK: undefined,
@@ -41,29 +39,12 @@ function newCodeEditor () {
function finalize () {
thisObject.container.finalize()
thisObject.container = undefined
thisObject.iconOK = undefined
thisObject.iconNOT_OK = undefined
thisObject.payload = undefined
thisObject.isVisibleFunction = undefined
}
function initialize () {
/* Load Images */
thisObject.iconOK = new Image()
thisObject.iconOK.onload = onImageLoad
function onImageLoad () {
thisObject.iconNOT_OK = new Image()
thisObject.iconNOT_OK.onload = onImageLoad
function onImageLoad () {
thisObject.canDrawIcon = true
}
thisObject.iconNOT_OK.src = window.canvasApp.urlPrefix + thisObject.imagePathNOT_OK
}
// thisObject.iconOK.src = window.canvasApp.urlPrefix + thisObject.imagePathOK
// thisObject.icon = thisObject.iconOK // The default value is ON.
}
function deactivate () {
+786 -130
View File
@@ -4,14 +4,9 @@ function newConditionEditor () {
let thisObject = {
isVisibleFunction: undefined,
iconOK: undefined,
iconNOT_OK: undefined,
visible: false,
imagePathOK: undefined,
imagePathNOT_OK: undefined,
rawRadius: undefined,
targetRadius: undefined,
currentRadius: undefined,
container: undefined,
payload: undefined,
deactivate: deactivate,
@@ -25,93 +20,620 @@ function newConditionEditor () {
}
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.initialize(MODULE_NAME, 'Circle')
thisObject.container.isClickeable = false
thisObject.container.isDraggeable = false
thisObject.container.detectMouseOver = false
thisObject.container.frame.radius = 0
thisObject.container.frame.position.x = 0
thisObject.container.frame.position.y = 0
thisObject.container.frame.radius = 750
thisObject.container.frame.containerName = MODULE_NAME
let isMouseOver = false
let conditionStructure
let scanResult
return thisObject
function finalize () {
thisObject.container.finalize()
thisObject.container = undefined
thisObject.iconOK = undefined
thisObject.iconNOT_OK = undefined
thisObject.payload = undefined
thisObject.isVisibleFunction = undefined
conditionStructure = undefined
scanResult = undefined
}
function initialize () {
/* Load Images */
thisObject.iconOK = new Image()
thisObject.iconOK.onload = onImageLoad
function onImageLoad () {
thisObject.iconNOT_OK = new Image()
thisObject.iconNOT_OK.onload = onImageLoad
function onImageLoad () {
thisObject.canDrawIcon = true
}
thisObject.iconNOT_OK.src = window.canvasApp.urlPrefix + thisObject.imagePathNOT_OK
}
// thisObject.iconOK.src = window.canvasApp.urlPrefix + thisObject.imagePathOK
// thisObject.icon = thisObject.iconOK // The default value is ON.
}
function deactivate () {
if (thisObject.visible === true) {
thisObject.visible = false
let textArea = document.getElementById('textArea')
textArea.style.display = 'none'
thisObject.payload.node.code = textArea.value
}
EDITOR_ON_FOCUS = false
}
function activate (payload) {
thisObject.visible = true
thisObject.payload = payload
thisObject.rawRadius = 8
thisObject.targetRadius = thisObject.container.frame.radius
thisObject.currentRadius = 0
thisObject.payload.uiObject.setErrorMessage('', 0)
let textArea = document.getElementById('textArea')
textArea.value = payload.node.code
textArea.style = 'resize: none;' +
' border: none;' +
' outline: none;' +
'box-shadow: none;' +
'overflow:hidden;' +
'font-family: ' + UI_FONT.PRIMARY + ';' +
'font-size: 14px;' +
'background-color: rgb(' + UI_COLOR.GREEN + ');' +
'color:rgb(255, 255, 255);' +
'width: ' + thisObject.container.frame.width + 'px;' +
'height: ' + thisObject.container.frame.height + 'px'
textArea.style.display = 'block'
textArea.focus()
conditionStructure = {
code: thisObject.payload.node.code,
orOperands: []
}
scanDataMines()
loadFromCode()
EDITOR_ON_FOCUS = true
}
function deactivate () {
convertToCode()
finalizePickers()
conditionStructure = undefined
if (thisObject.visible === true) {
thisObject.visible = false
}
EDITOR_ON_FOCUS = false
}
function loadFromCode () {
if (thisObject.payload.node.code === undefined || thisObject.payload.node.code === '') { return }
/* LOGICAL ORs */
let orArray = conditionStructure.code.split(' || ')
for (let j = 0; j < orArray.length; j++) {
let logicOperand = {
code: orArray[j],
index: j,
comparison: {}
}
checkComparison(logicOperand, j)
conditionStructure.orOperands.push(logicOperand)
}
function checkComparison (logicOperand) {
/* We are going to decompose the code into 2 comparison operators */
logicOperand.comparison.operandA = { index: 0}
logicOperand.comparison.operandB = { index: 1}
if (logicOperand.code.indexOf(' > ') > 0) {
let codeArray = logicOperand.code.split(' > ')
logicOperand.comparison.operandA.code = codeArray[0]
logicOperand.comparison.operandB.code = codeArray[1]
logicOperand.comparison.operator = ' > '
logicOperand.comparison.operatorIndex = 0
}
if (logicOperand.code.indexOf(' < ') > 0) {
let codeArray = logicOperand.code.split(' < ')
logicOperand.comparison.operandA.code = codeArray[0]
logicOperand.comparison.operandB.code = codeArray[1]
logicOperand.comparison.operator = ' < '
logicOperand.comparison.operatorIndex = 1
}
if (logicOperand.code.indexOf(' >= ') > 0) {
let codeArray = logicOperand.code.split(' >= ')
logicOperand.comparison.operandA.code = codeArray[0]
logicOperand.comparison.operandB.code = codeArray[1]
logicOperand.comparison.operator = ' >= '
logicOperand.comparison.operatorIndex = 2
}
if (logicOperand.code.indexOf(' <= ') > 0) {
let codeArray = logicOperand.code.split(' <= ')
logicOperand.comparison.operandA.code = codeArray[0]
logicOperand.comparison.operandB.code = codeArray[1]
logicOperand.comparison.operator = ' <= '
logicOperand.comparison.operatorIndex = 3
}
if (logicOperand.code.indexOf(' === ') > 0) {
let codeArray = logicOperand.code.split(' === ')
logicOperand.comparison.operandA.code = codeArray[0]
logicOperand.comparison.operandB.code = codeArray[1]
logicOperand.comparison.operator = ' === '
logicOperand.comparison.operatorIndex = 4
}
logicOperand.comparison.picker = newPicker()
let picker = logicOperand.comparison.picker
picker.name = 'Comparison'
picker.container.connectToParent(thisObject.container)
picker.container.frame.position.x = 0 - picker.container.frame.width / 2
picker.container.frame.position.y = 0 - picker.container.frame.height / 2
let optionsList = ['Greater Than', 'Less Than', 'Greater or Equal Than', 'Less or Equal Than', 'Equal To']
picker.initialize(optionsList)
picker.eventSuscriptionId = picker.container.eventHandler.listenToEvent('onParentChanged', onParentChanged)
/* Each comparison code may have one or more algebraic operators */
checkAlgebra(logicOperand, logicOperand.comparison.operandA)
checkAlgebra(logicOperand, logicOperand.comparison.operandB)
}
function checkAlgebra (logicOperand, comparisonOperand) {
comparisonOperand.algebra = {
operandA: { index: 0},
operandB: { index: 1}
}
/* The default situation is that there is no Algebraic operation, meaning we will setup a Algebraic operation only with operandA */
comparisonOperand.algebra.operandA.code = comparisonOperand.code
comparisonOperand.algebra.operandB.code = ''
comparisonOperand.algebra.operator = ' ... '
comparisonOperand.algebra.operatorIndex = 0
if (comparisonOperand.code.indexOf(' + ') > 0) {
let codeArray = logicOperand.code.split(' + ')
comparisonOperand.algebra.operandA.code = codeArray[0]
comparisonOperand.algebra.operandB.code = codeArray[1]
comparisonOperand.algebra.operator = ' + '
comparisonOperand.algebra.operatorIndex = 1
}
if (comparisonOperand.code.indexOf(' - ') > 0) {
let codeArray = logicOperand.code.split(' - ')
comparisonOperand.algebra.operandA.code = codeArray[0]
comparisonOperand.algebra.operandB.code = codeArray[1]
comparisonOperand.algebra.operator = ' - '
comparisonOperand.algebra.operatorIndex = 2
}
if (comparisonOperand.code.indexOf(' * ') > 0) {
let codeArray = logicOperand.code.split(' * ')
comparisonOperand.algebra.operandA.code = codeArray[0]
comparisonOperand.algebra.operandB.code = codeArray[1]
comparisonOperand.algebra.operator = ' * '
comparisonOperand.algebra.operatorIndex = 3
}
if (comparisonOperand.code.indexOf(' / ') > 0) {
let codeArray = logicOperand.code.split(' / ')
comparisonOperand.algebra.operandA.code = codeArray[0]
comparisonOperand.algebra.operandB.code = codeArray[1]
comparisonOperand.algebra.operator = ' / '
comparisonOperand.algebra.operatorIndex = 4
}
initializePickersSet(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA)
initializePickersSet(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA)
updatePickers(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA)
updatePickers(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA)
}
function initializePickersSet (logicOperand, comparisonOperand, algebraOperand) {
/* Get the ySign */
let ySign
if (algebraOperand.index === 0) {
ySign = -1
}
if (algebraOperand.index === 1) {
ySign = 1
}
let properties
let parent
let current
algebraOperand.whenPicker = newPicker()
algebraOperand.whenPicker.name = 'When'
algebraOperand.whenPicker.container.connectToParent(thisObject.container)
algebraOperand.whenPicker.container.frame.position.x = 0 - algebraOperand.whenPicker.container.frame.width / 2 - algebraOperand.whenPicker.container.frame.width * 1.0
algebraOperand.whenPicker.container.frame.position.y = 0 - algebraOperand.whenPicker.container.frame.height / 2 + algebraOperand.whenPicker.container.frame.height * ySign
current = ['Current', '1 Previous', '2 Previous', '3 Previous', '4 Previous', '5 Previous']
algebraOperand.whenPicker.initialize(current, current)
algebraOperand.whenPicker.visible = true
algebraOperand.algebraicPicker = newPicker()
algebraOperand.algebraicPicker.name = 'Algebraic'
algebraOperand.algebraicPicker.container.connectToParent(thisObject.container)
algebraOperand.algebraicPicker.container.frame.position.x = 0 - algebraOperand.algebraicPicker.container.frame.width / 2 + algebraOperand.algebraicPicker.container.frame.width * 3.0
algebraOperand.algebraicPicker.container.frame.position.y = 0 - algebraOperand.algebraicPicker.container.frame.height / 2 + algebraOperand.algebraicPicker.container.frame.height * ySign
current = ['+ - * /', 'Plus', 'Minus', 'Times', 'Divided by']
algebraOperand.algebraicPicker.initialize(current, current)
algebraOperand.algebraicPicker.visible = true
algebraOperand.dataMinePicker = newPicker()
algebraOperand.dataMinePicker.name = 'Data Mine'
algebraOperand.dataMinePicker.container.connectToParent(thisObject.container)
algebraOperand.dataMinePicker.container.frame.position.x = 0 - algebraOperand.dataMinePicker.container.frame.width / 2 - algebraOperand.dataMinePicker.container.frame.width * 3.0
algebraOperand.dataMinePicker.container.frame.position.y = 0 - algebraOperand.dataMinePicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign
current = scanResult
properties = Object.keys(current)
algebraOperand.dataMinePicker.initialize(properties, current)
parent = current
algebraOperand.dataMinePicker.visible = true
algebraOperand.botPicker = newPicker()
algebraOperand.botPicker.name = 'Bot'
algebraOperand.botPicker.container.connectToParent(thisObject.container)
algebraOperand.botPicker.container.frame.position.x = 0 - algebraOperand.botPicker.container.frame.width / 2 - algebraOperand.botPicker.container.frame.width * 2.0
algebraOperand.botPicker.container.frame.position.y = 0 - algebraOperand.botPicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign
current = parent[properties[0]]
properties = Object.keys(current)
algebraOperand.botPicker.initialize(properties, current, parent)
parent = current
algebraOperand.botPicker.visible = true
algebraOperand.productPicker = newPicker()
algebraOperand.productPicker.name = 'Product'
algebraOperand.productPicker.container.connectToParent(thisObject.container)
algebraOperand.productPicker.container.frame.position.x = 0 - algebraOperand.productPicker.container.frame.width / 2 + algebraOperand.productPicker.container.frame.width * 0.0
algebraOperand.productPicker.container.frame.position.y = 0 - algebraOperand.productPicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign
current = parent[properties[0]]
properties = Object.keys(current)
algebraOperand.productPicker.initialize(properties, current, parent)
parent = current
algebraOperand.productPicker.visible = true
let productParent = parent
let productProperties = properties
algebraOperand.propertyPicker = newPicker()
algebraOperand.propertyPicker.name = 'Property'
algebraOperand.propertyPicker.container.connectToParent(thisObject.container)
algebraOperand.propertyPicker.container.frame.position.x = 0 - algebraOperand.propertyPicker.container.frame.width / 2 + algebraOperand.propertyPicker.container.frame.width * 1.0
algebraOperand.propertyPicker.container.frame.position.y = 0 - algebraOperand.propertyPicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign
current = productParent[productProperties[0]]
current = current.properties
properties = Object.keys(current)
algebraOperand.propertyPicker.initialize(properties, current, productParent, 'properties')
parent = current
algebraOperand.propertyPicker.visible = true
algebraOperand.valuePicker = newPicker()
algebraOperand.valuePicker.name = 'Value'
algebraOperand.valuePicker.container.connectToParent(thisObject.container)
algebraOperand.valuePicker.container.frame.position.x = 0 - algebraOperand.valuePicker.container.frame.width / 2
algebraOperand.valuePicker.container.frame.position.y = 0 - algebraOperand.valuePicker.container.frame.height / 2 + algebraOperand.valuePicker.container.frame.height * 1
current = parent[properties[0]]
properties = current.possibleValues
algebraOperand.valuePicker.initialize(properties, current, parent, 'possibleValues')
parent = current
algebraOperand.valuePicker.visible = false
algebraOperand.timeFramePicker = newPicker()
algebraOperand.timeFramePicker.name = 'Time Frame'
algebraOperand.timeFramePicker.container.connectToParent(thisObject.container)
algebraOperand.timeFramePicker.container.frame.position.x = 0 - algebraOperand.timeFramePicker.container.frame.width / 2 + algebraOperand.timeFramePicker.container.frame.width * 2.0
algebraOperand.timeFramePicker.container.frame.position.y = 0 - algebraOperand.timeFramePicker.container.frame.height / 2 + algebraOperand.timeFramePicker.container.frame.height * ySign
current = productParent[productProperties[0]]
properties = current.validTimeFrames
algebraOperand.timeFramePicker.initialize(properties, current, productParent, 'validTimeFrames')
parent = current
algebraOperand.timeFramePicker.visible = true
algebraOperand.botPicker.eventSuscriptionId = algebraOperand.dataMinePicker.container.eventHandler.listenToEvent('onParentChanged', algebraOperand.botPicker.onParentChanged)
algebraOperand.productPicker.eventSuscriptionId = algebraOperand.botPicker.container.eventHandler.listenToEvent('onParentChanged', algebraOperand.productPicker.onParentChanged)
algebraOperand.propertyPicker.eventSuscriptionId = algebraOperand.productPicker.container.eventHandler.listenToEvent('onParentChanged', algebraOperand.propertyPicker.onParentChanged)
algebraOperand.valuePicker.eventSuscriptionId = algebraOperand.propertyPicker.container.eventHandler.listenToEvent('onParentChanged', algebraOperand.valuePicker.onParentChanged)
algebraOperand.timeFramePicker.eventSuscriptionId = algebraOperand.productPicker.container.eventHandler.listenToEvent('onParentChanged', algebraOperand.timeFramePicker.onParentChanged)
}
function updatePickers (logicOperand, comparisonOperand, algebraOperand) {
let codeArray = algebraOperand.code.split('.')
let codeTimeFrame = codeArray[1].substring(2, 4) + '-' + codeArray[1].substring(4, 7)
let codeProduct = codeArray[2]
/* Parse When */
let propertyDisplacement = 0
let codeWhen = 'Current'
if (codeArray[3] === 'previous') {
propertyDisplacement++
codeWhen = '1 Previous'
}
if (codeArray[4] === 'previous') {
propertyDisplacement++
codeWhen = '2 Previous'
}
if (codeArray[5] === 'previous') {
propertyDisplacement++
codeWhen = '3 Previous'
}
if (codeArray[6] === 'previous') {
propertyDisplacement++
codeWhen = '4 Previous'
}
if (codeArray[7] === 'previous') {
propertyDisplacement++
codeWhen = '5 Previous'
}
algebraOperand.whenPicker.setSelected(undefined, undefined, undefined, propertyDisplacement)
let codeProperty = codeArray[3 + propertyDisplacement]
let codeValue = comparisonOperand.algebra.operandB.code.replace('"', '').replace('"', '')
let dataMines = Object.keys(scanResult)
for (let i = 0; i < dataMines.length; i++) {
let dataMine = dataMines[i]
let dataMineObject = scanResult[dataMine]
let bots = Object.keys(dataMineObject)
for (let j = 0; j < bots.length; j++) {
let bot = bots[j]
let botObject = dataMineObject[bot]
let products = Object.keys(botObject)
for (let k = 0; k < products.length; k++) {
let product = products[k]
let productObject = botObject[product]
if (codeProduct === product) {
algebraOperand.dataMinePicker.setSelected(dataMines, scanResult, undefined, i)
algebraOperand.botPicker.setSelected(bots, dataMineObject, scanResult, j)
algebraOperand.productPicker.setSelected(products, botObject, dataMineObject, k)
let properties = Object.keys(productObject.properties)
for (let m = 0; m < properties.length; m++) {
let property = properties[m]
let propertyObject = productObject.properties[property]
if (codeProperty === property) {
algebraOperand.propertyPicker.setSelected(properties, productObject.properties, botObject, m)
let values = propertyObject.possibleValues
for (let n = 0; n < values.length; n++) {
let value = values[n]
let valueObject = propertyObject[value]
if (codeValue === value) {
algebraOperand.valuePicker.setSelected(values, propertyObject, productObject, n)
}
}
}
}
let timeFrames = productObject.validTimeFrames
for (let m = 0; m < timeFrames.length; m++) {
let timeFrame = timeFrames[m]
let timeFrameObject = productObject.validTimeFrames[timeFrame]
if (codeTimeFrame === timeFrame) {
algebraOperand.timeFramePicker.setSelected(timeFrames, productObject, botObject, m)
}
}
}
}
}
}
}
}
function scanDataMines () {
let selector = {}
let workspace = canvas.designSpace.workspace.workspaceNode
for (let i = 0; i < workspace.rootNodes.length; i++) {
let rootNode = workspace.rootNodes[i]
if (rootNode.type !== 'Data Mine') { continue }
let dataMine = rootNode
let dataMineName = loadPropertyFromNodeConfig(dataMine.payload, 'codeName')
selector[dataMineName] = {}
let bots = dataMine.sensorBots.concat(dataMine.indicatorBots)
for (let j = 0; j < bots.length; j++) {
let bot = bots[j]
let botName = loadPropertyFromNodeConfig(bot.payload, 'codeName')
let selectorDataMine = selector[dataMineName]
selectorDataMine[botName] = {}
for (let k = 0; k < bot.products.length; k++) {
let product = bot.products[k]
let productName = loadPropertyFromNodeConfig(product.payload, 'singularVariableName')
if (productName === undefined) { continue }
let selectorProduct = selectorDataMine[botName]
selectorProduct[productName] = {
properties: {}
}
if (product.record === undefined) { continue }
for (let m = 0; m < product.record.properties.length; m++) {
let property = product.record.properties[m]
let propertyName = loadPropertyFromNodeConfig(property.payload, 'codeName')
let selectorProperty = selectorProduct[productName]
selectorProperty = selectorProperty.properties
selectorProperty[propertyName] = {}
let possibleValues = loadPropertyFromNodeConfig(property.payload, 'possibleValues')
if (possibleValues === undefined) { possibleValues = [] }
let selectorPossibleValue = selectorProperty[propertyName]
selectorPossibleValue.possibleValues = possibleValues
}
let allPossibleTimeFrames = []
for (let m = 0; m < product.datasets.length; m++) {
let dataset = product.datasets[m]
let validTimeFrames = loadPropertyFromNodeConfig(dataset.payload, 'validTimeFrames')
if (validTimeFrames !== undefined) {
allPossibleTimeFrames = allPossibleTimeFrames.concat(validTimeFrames)
}
}
let selectorValidTimeFrames = selectorProduct[productName]
selectorValidTimeFrames.validTimeFrames = allPossibleTimeFrames
let productKeys = Object.keys(selectorProduct[productName])
if (productKeys.length === 0) {
selectorProduct[productName] = undefined
}
}
let botKeys = Object.keys(selectorDataMine[botName])
if (botKeys.length === 0) {
selectorDataMine[botName] = undefined
}
}
let dataMineKeys = Object.keys(selector[dataMineName])
if (dataMineKeys.length === 0) {
selector[dataMineName] = undefined
}
}
scanResult = JSON.parse(JSON.stringify(selector))
}
function convertToCode () {
// if (comparisonOperatorA === undefined || comparisonOperatorB === undefined || comparisonPicker === undefined) { return }
// chart.at01hs.bollingerSubChannel.previous.previous.slope=== "Extreme"
/*
let code = ''
code = code + 'chart.at' + comparisonOperatorA.timeFramePicker.getSelected().replace('-', '')
code = code + '.' + comparisonOperatorA.productPicker.getSelected()
insertWhen(comparisonOperatorA)
code = code + '.' + comparisonOperatorA.propertyPicker.getSelected()
switch (comparisonPicker.getSelected()) {
case 'Greater Than': {
code = code + ' > '
break
}
case 'Less Than': {
code = code + ' < '
break
}
case 'Greater or Equal Than': {
code = code + ' >= '
break
}
case 'Less or Equal Than': {
code = code + ' <= '
break
}
case 'Equal To': {
code = code + ' === '
break
}
}
if (comparisonPicker.getSelected() === 'Equal To') {
code = code + '"' + comparisonOperatorA.valuePicker.getSelected() + '"'
} else {
code = code + 'chart.at' + comparisonOperatorB.timeFramePicker.getSelected().replace('-', '')
code = code + '.' + comparisonOperatorB.productPicker.getSelected()
insertWhen(comparisonOperatorB)
code = code + '.' + comparisonOperatorB.propertyPicker.getSelected()
}
thisObject.payload.node.code = code
function insertWhen (operator) {
switch (operator.whenPicker.getSelected()) {
case 'Current': {
return
}
case '1 Previous': {
code = code + '.previous'
return
}
case '2 Previous': {
code = code + '.previous.previous'
return
}
case '3 Previous': {
code = code + '.previous.previous.previous'
return
}
case '4 Previous': {
code = code + '.previous.previous.previous.previous'
return
}
case '5 Previous': {
code = code + '.previous.previous.previous.previous.previous'
return
}
}
}
*/
}
function finalizePickers () {
if (conditionStructure === undefined) { return }
for (let i = 0; i < conditionStructure.orOperands.length; i++) {
let logicOperand = conditionStructure.orOperands[i]
finalizeOperator(logicOperand.comparison.operandA.algebra.operandA)
finalizeOperator(logicOperand.comparison.operandA.algebra.operandB)
finalizeOperator(logicOperand.comparison.operandB.algebra.operandA)
finalizeOperator(logicOperand.comparison.operandB.algebra.operandB)
}
}
function finalizeOperator (operand) {
if (operand === undefined) { return }
if (operand.whenPicker !== undefined) {
operand.whenPicker.finalize()
operand.whenPicker = undefined
}
if (operand.algebraicPicker !== undefined) {
operand.algebraicPicker.finalize()
operand.algebraicPicker = undefined
}
if (operand.dataMinePicker !== undefined) {
operand.dataMinePicker.container.eventHandler.stopListening(operand.botPicker.eventSuscriptionId)
operand.dataMinePicker.finalize()
operand.dataMinePicker = undefined
}
if (operand.botPicker !== undefined) {
operand.botPicker.container.eventHandler.stopListening(operand.productPicker.eventSuscriptionId)
operand.botPicker.finalize()
operand.botPicker = undefined
}
if (operand.productPicker !== undefined) {
operand.productPicker.container.eventHandler.stopListening(operand.propertyPicker.eventSuscriptionId)
operand.productPicker.container.eventHandler.stopListening(operand.timeFramePicker.eventSuscriptionId)
operand.productPicker.finalize()
operand.productPicker = undefined
}
if (operand.propertyPicker !== undefined) {
operand.propertyPicker.container.eventHandler.stopListening(operand.valuePicker.eventSuscriptionId)
operand.propertyPicker.finalize()
operand.propertyPicker = undefined
}
if (operand.valuePicker !== undefined) {
operand.valuePicker.finalize()
operand.valuePicker = undefined
}
if (operand.timeFramePicker !== undefined) {
operand.timeFramePicker.finalize()
operand.timeFramePicker = undefined
}
}
function onParentChanged (event) {
if (event.selected === 4) {
// this means Equal To
comparisonOperatorA.valuePicker.visible = true
comparisonOperatorB.whenPicker.visible = false
comparisonOperatorB.algebraicPicker.visible = false
comparisonOperatorB.dataMinePicker.visible = false
comparisonOperatorB.botPicker.visible = false
comparisonOperatorB.productPicker.visible = false
comparisonOperatorB.propertyPicker.visible = false
comparisonOperatorB.timeFramePicker.visible = false
} else {
comparisonOperatorA.valuePicker.visible = false
comparisonOperatorB.whenPicker.visible = true
comparisonOperatorB.algebraicPicker.visible = true
comparisonOperatorB.dataMinePicker.visible = true
comparisonOperatorB.botPicker.visible = true
comparisonOperatorB.productPicker.visible = true
comparisonOperatorB.propertyPicker.visible = true
comparisonOperatorB.timeFramePicker.visible = true
}
}
function getContainer (point) {
let container
if (thisObject.visible === true) {
if (point.x === VERY_LARGE_NUMBER) {
/* The the mouse leaves the canvas, and event of mouse over with a ridiculous coordinate is triggered so that
anyone can react. In our case, the code editor has a text area that is not part of the canvas, so the event is
triggered. We compensate recognizing this coordinate and returning our container. */
return thisObject.container
if (conditionStructure === undefined) { return }
for (let i = 0; i < conditionStructure.orOperands.length; i++) {
let logicOperand = conditionStructure.orOperands[i]
container = operandGetContainer(point, logicOperand.comparison.operandA.algebra.operandA)
if (container !== undefined) { return container }
container = operandGetContainer(point, logicOperand.comparison.operandA.algebra.operandB)
if (container !== undefined) { return container }
container = operandGetContainer(point, logicOperand.comparison.operandB.algebra.operandA)
if (container !== undefined) { return container }
container = operandGetContainer(point, logicOperand.comparison.operandB.algebra.operandB)
if (container !== undefined) { return container }
}
if (thisObject.container.frame.isThisPointHere(point, true, false) === true) {
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
return thisObject.container
} else {
return undefined
@@ -119,43 +641,139 @@ function newConditionEditor () {
}
}
function physics () {
if (Math.abs(thisObject.currentRadius - thisObject.targetRadius) >= 0.5) {
if (thisObject.currentRadius < thisObject.targetRadius) {
thisObject.currentRadius = thisObject.currentRadius + 0.5
} else {
thisObject.currentRadius = thisObject.currentRadius - 0.5
function operandGetContainer (point, operand) {
let container
if (operand.whenPicker !== undefined) {
if (operand.whenPicker.visible === true) {
container = operand.whenPicker.getContainer(point)
if (container !== undefined) { return container }
}
}
thisObject.container.frame.position.x = 0
thisObject.container.frame.position.y = 0
thisObject.container.frame.width = thisObject.container.frame.radius * 1.8 * 2
thisObject.container.frame.height = thisObject.container.frame.radius * 1 * 2
let textAreaPosition = {
x: 0 - thisObject.container.frame.width / 2,
y: 0 - thisObject.container.frame.height * 3 / 7 + CURRENT_TOP_MARGIN
}
textAreaPosition = thisObject.container.frame.frameThisPoint(textAreaPosition)
if (thisObject.visible === true) {
let checkPosition = {
x: textAreaPosition.x,
y: textAreaPosition.y - CURRENT_TOP_MARGIN
}
if (thisObject.isVisibleFunction(checkPosition) === false) {
deactivate()
if (operand.algebraicPicker !== undefined) {
if (operand.algebraicPicker.visible === true) {
container = operand.algebraicPicker.getContainer(point)
if (container !== undefined) { return container }
}
}
if (thisObject.visible === true) {
let textAreaDiv = document.getElementById('textAreaDiv')
textAreaDiv.style = 'position:fixed; top:' + textAreaPosition.y + 'px; left:' + textAreaPosition.x + 'px; z-index:1; '
if (operand.dataMinePicker !== undefined) {
if (operand.dataMinePicker.visible === true) {
container = operand.dataMinePicker.getContainer(point)
if (container !== undefined) { return container }
}
}
if (operand.botPicker !== undefined) {
if (operand.botPicker.visible === true) {
container = operand.botPicker.getContainer(point)
if (container !== undefined) { return container }
}
}
if (operand.productPicker !== undefined) {
if (operand.productPicker.visible === true) {
container = operand.productPicker.getContainer(point)
if (container !== undefined) { return container }
}
}
if (operand.propertyPicker !== undefined) {
if (operand.propertyPicker.visible === true) {
container = operand.propertyPicker.getContainer(point)
if (container !== undefined) { return container }
}
}
if (operand.valuePicker !== undefined) {
if (operand.valuePicker.visible === true) {
container = operand.valuePicker.getContainer(point)
if (container !== undefined) { return container }
}
}
if (operand.timeFramePicker !== undefined) {
if (operand.timeFramePicker.visible === true) {
container = operand.timeFramePicker.getContainer(point)
if (container !== undefined) { return container }
}
}
}
function physics () {
}
function drawBackground () {
thisObjectDrawBackground()
childrenDrawBackground()
}
function childrenDrawBackground () {
if (conditionStructure === undefined) { return }
for (let i = 0; i < conditionStructure.orOperands.length; i++) {
let logicOperand = conditionStructure.orOperands[i]
operandDrawBackground(logicOperand.comparison.operandA.algebra.operandA)
operandDrawBackground(logicOperand.comparison.operandA.algebra.operandB)
operandDrawBackground(logicOperand.comparison.operandB.algebra.operandA)
operandDrawBackground(logicOperand.comparison.operandB.algebra.operandB)
}
}
function operandDrawBackground (operand) {
if (operand === undefined) { return }
if (operand.whenPicker !== undefined) {
if (operand.whenPicker.visible === true) {
operand.whenPicker.drawBackground()
}
}
if (operand.algebraicPicker !== undefined) {
if (operand.algebraicPicker.visible === true) {
operand.algebraicPicker.drawBackground()
}
}
if (operand.dataMinePicker !== undefined) {
if (operand.dataMinePicker.visible === true) {
operand.dataMinePicker.drawBackground()
}
}
if (operand.botPicker !== undefined) {
if (operand.botPicker.visible === true) {
operand.botPicker.drawBackground()
}
}
if (operand.productPicker !== undefined) {
if (operand.productPicker.visible === true) {
operand.productPicker.drawBackground()
}
}
if (operand.propertyPicker !== undefined) {
if (operand.propertyPicker.visible === true) {
operand.propertyPicker.drawBackground()
}
}
if (operand.valuePicker !== undefined) {
if (operand.valuePicker.visible === true) {
operand.valuePicker.drawBackground()
}
}
if (operand.timeFramePicker !== undefined) {
if (operand.timeFramePicker.visible === true) {
operand.timeFramePicker.drawBackground()
}
}
}
function thisObjectDrawBackground () {
if (thisObject.visible === true) {
let position = {
x: 0,
@@ -164,54 +782,92 @@ function newConditionEditor () {
position = thisObject.container.frame.frameThisPoint(position)
let radius = thisObject.container.frame.radius * 2
let radius = thisObject.container.frame.radius
if (radius > 0.5) {
browserCanvasContext.beginPath()
browserCanvasContext.arc(position.x, position.y, radius * 1.3 + 3, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + 1 + ')'
browserCanvasContext.fill()
browserCanvasContext.beginPath()
browserCanvasContext.arc(position.x, position.y, radius + 3, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + 1 + ')'
browserCanvasContext.fill()
browserCanvasContext.beginPath()
browserCanvasContext.arc(position.x, position.y, radius * 1.3, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + 1 + ')'
browserCanvasContext.fill()
browserCanvasContext.beginPath()
browserCanvasContext.arc(position.x, position.y, radius, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREY + ', ' + 1 + ')'
browserCanvasContext.fill()
}
}
function drawForeground () {
thisObjectDrawForeground()
childrenDrawForeground()
}
function childrenDrawForeground () {
if (conditionStructure === undefined) { return }
for (let i = 0; i < conditionStructure.orOperands.length; i++) {
let logicOperand = conditionStructure.orOperands[i]
operandDrawForeground(logicOperand.comparison.operandA.algebra.operandA)
operandDrawForeground(logicOperand.comparison.operandA.algebra.operandB)
operandDrawForeground(logicOperand.comparison.operandB.algebra.operandA)
operandDrawForeground(logicOperand.comparison.operandB.algebra.operandB)
}
}
function operandDrawForeground (operand) {
if (operand === undefined) { return }
if (operand.whenPicker !== undefined) {
if (operand.whenPicker.visible === true) {
operand.whenPicker.drawForeground()
}
}
if (operand.algebraicPicker !== undefined) {
if (operand.algebraicPicker.visible === true) {
operand.algebraicPicker.drawForeground()
}
}
if (operand.dataMinePicker !== undefined) {
if (operand.dataMinePicker.visible === true) {
operand.dataMinePicker.drawForeground()
}
}
if (operand.botPicker !== undefined) {
if (operand.botPicker.visible === true) {
operand.botPicker.drawForeground()
}
}
if (operand.productPicker !== undefined) {
if (operand.productPicker.visible === true) {
operand.productPicker.drawForeground()
}
}
if (operand.propertyPicker !== undefined) {
if (operand.propertyPicker.visible === true) {
operand.propertyPicker.drawForeground()
}
}
if (operand.valuePicker !== undefined) {
if (operand.valuePicker.visible === true) {
operand.valuePicker.drawForeground()
}
}
if (operand.timeFramePicker !== undefined) {
if (operand.timeFramePicker.visible === true) {
operand.timeFramePicker.drawForeground()
}
}
}
function drawForeground () {
let iconPosition = {
x: 0,
y: thisObject.currentRadius * 1.5
}
iconPosition = thisObject.container.frame.frameThisPoint(iconPosition)
function thisObjectDrawForeground () {
/* Menu Item */
if (thisObject.canDrawIcon === true && thisObject.currentRadius > 1) {
browserCanvasContext.drawImage(thisObject.icon, iconPosition.x - thisObject.currentRadius, iconPosition.y - thisObject.currentRadius, thisObject.currentRadius * 2, thisObject.currentRadius * 2)
/* Menu Label */
let label = 'Code looks good!'
let labelPoint
let fontSize = 10
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
if (label !== undefined && thisObject.currentRadius >= thisObject.targetRadius) {
labelPoint = {
x: iconPosition.x + thisObject.currentRadius + 10,
y: iconPosition.y + fontSize * FONT_ASPECT_RATIO
}
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
}
}
}
-19
View File
@@ -4,8 +4,6 @@ function newConfigEditor () {
let thisObject = {
isVisibleFunction: undefined,
iconOK: undefined,
iconNOT_OK: undefined,
visible: false,
imagePathOK: undefined,
imagePathNOT_OK: undefined,
@@ -41,29 +39,12 @@ function newConfigEditor () {
function finalize () {
thisObject.container.finalize()
thisObject.container = undefined
thisObject.iconOK = undefined
thisObject.iconNOT_OK = undefined
thisObject.payload = undefined
thisObject.isVisibleFunction = undefined
}
function initialize () {
/* Load Images */
thisObject.iconOK = new Image()
thisObject.iconOK.onload = onImageLoad
function onImageLoad () {
thisObject.iconNOT_OK = new Image()
thisObject.iconNOT_OK.onload = onImageLoad
function onImageLoad () {
thisObject.canDrawIcon = true
}
thisObject.iconNOT_OK.src = window.canvasApp.urlPrefix + thisObject.imagePathNOT_OK
}
// thisObject.iconOK.src = window.canvasApp.urlPrefix + thisObject.imagePathOK
// thisObject.icon = thisObject.iconOK // The default value is ON.
}
function deactivate () {
-19
View File
@@ -4,8 +4,6 @@ function newFormulaEditor () {
let thisObject = {
isVisibleFunction: undefined,
iconOK: undefined,
iconNOT_OK: undefined,
visible: false,
imagePathOK: undefined,
imagePathNOT_OK: undefined,
@@ -41,29 +39,12 @@ function newFormulaEditor () {
function finalize () {
thisObject.container.finalize()
thisObject.container = undefined
thisObject.iconOK = undefined
thisObject.iconNOT_OK = undefined
thisObject.payload = undefined
thisObject.isVisibleFunction = undefined
}
function initialize () {
/* Load Images */
thisObject.iconOK = new Image()
thisObject.iconOK.onload = onImageLoad
function onImageLoad () {
thisObject.iconNOT_OK = new Image()
thisObject.iconNOT_OK.onload = onImageLoad
function onImageLoad () {
thisObject.canDrawIcon = true
}
thisObject.iconNOT_OK.src = window.canvasApp.urlPrefix + thisObject.imagePathNOT_OK
}
// thisObject.iconOK.src = window.canvasApp.urlPrefix + thisObject.imagePathOK
// thisObject.icon = thisObject.iconOK // The default value is ON.
}
function deactivate () {
+220
View File
@@ -0,0 +1,220 @@
function newPicker () {
const MODULE_NAME = 'Picker'
let thisObject = {
container: undefined,
selectedItem: 0,
onParentChanged: onParentChanged,
getSelected: getSelected,
setSelected: setSelected,
physics: physics,
drawBackground: drawBackground,
drawForeground: drawForeground,
getContainer: getContainer,
finalize: finalize,
initialize: initialize
}
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.isClickeable = false
thisObject.container.isDraggeable = false
thisObject.container.isWheelable = true
thisObject.container.detectMouseOver = true
thisObject.container.frame.radius = 0
thisObject.container.frame.position.x = 0
thisObject.container.frame.position.y = 0
thisObject.container.frame.width = 200
thisObject.container.frame.height = 120
let isMouseOver
let optionsList
let parent
let current
let parentSelected = 0
let propertyName
let selected = 0
let lastSelected = 0
let onMouseWheelEventSubscriptionId
let onMouseOverEventSubscriptionId
let onMouseNotOverEventSubscriptionId
return thisObject
function finalize () {
thisObject.container.eventHandler.stopListening(onMouseWheelEventSubscriptionId)
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
thisObject.container.finalize()
thisObject.container = undefined
optionsList = undefined
parent = undefined
current = undefined
}
function initialize (pOptionsList, pCurrent, pParent, pPropertyName) {
optionsList = pOptionsList
current = pCurrent
parent = pParent
propertyName = pPropertyName
onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
}
function onMouseOver (event) {
isMouseOver = true
}
function onMouseNotOver () {
isMouseOver = false
}
function getSelected () {
return optionsList[selected]
}
function setSelected (pOptionsList, pCurrent, pParent, pSelected) {
if (pOptionsList !== undefined) {
optionsList = pOptionsList
}
if (pCurrent !== undefined) {
current = pCurrent
}
if (pParent !== undefined) {
parent = pParent
}
if (pSelected !== undefined) {
selected = pSelected
}
raiseEventParentChanged()
}
function onParentChanged (event) {
if (event.parent !== undefined) {
parent = event.parent
}
parentSelected = event.selected
selected = 0
let parentKeys
parentKeys = Object.keys(parent)
checkPropertyName()
function checkPropertyName () {
if (propertyName === undefined) {
current = parent[parentKeys[parentSelected]]
checkArray()
} else {
current = parent[parentKeys[parentSelected]]
current = current[propertyName]
checkArray()
}
}
function checkArray () {
if (Array.isArray(current) === false) {
optionsList = Object.keys(current)
} else {
optionsList = current
}
}
raiseEventParentChanged()
}
function getContainer (point) {
let container
if (thisObject.container.frame.isThisPointHere(point, true, false) === true) {
return thisObject.container
}
}
function getSelected () {
return optionsList[selected]
}
function onMouseWheel () {
delta = event.wheelDelta
if (delta > 0) {
delta = -1
} else {
delta = 1
}
selected = selected + delta
if (selected < 0) { selected = 0 }
if (selected > optionsList.length - 1) {
selected = optionsList.length - 1
}
if (selected !== lastSelected) {
lastSelected = selected
raiseEventParentChanged()
}
}
function raiseEventParentChanged () {
let event = {
selected: selected,
parent: current,
propertyName: propertyName
}
thisObject.container.eventHandler.raiseEvent('onParentChanged', event)
}
function physics () {
}
function drawBackground () {
}
function drawForeground () {
const FONT_SIZE = 20
const VISIBLE_LABELS = 5
let fontSize
let fontColor
let opacity
for (let i = 0; i < VISIBLE_LABELS; i++) {
let index = i - 2 + selected
let label = ''
if (index >= 0 && index < optionsList.length) {
label = optionsList[index]
}
fontColor = UI_COLOR.LIGHT_GREY
switch (i) {
case 0:
fontSize = FONT_SIZE - 10
opacity = 0.4
break
case 1:
fontSize = FONT_SIZE - 5
opacity = 0.5
break
case 2:
fontSize = FONT_SIZE - 0
fontColor = UI_COLOR.BLACK
opacity = 1
break
case 3:
fontSize = FONT_SIZE - 5
opacity = 0.5
break
case 4:
fontSize = FONT_SIZE - 10
opacity = 0.4
break
}
if (i === 2 || isMouseOver === true) {
drawLabel(label, 1 / 2, i / VISIBLE_LABELS, 0, 0, fontSize, thisObject.container, fontColor, undefined, undefined, opacity)
}
}
}
}
+23 -12
View File
@@ -117,17 +117,12 @@ function newUiObject () {
let referenceLineCounter = 0
let chainLineCounter = 0
let eventsServerClient
return thisObject
function finalize () {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
if (eventSubscriptionIdOnRunning !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject')
}
if (eventSubscriptionIdOnStopped !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnStopped, 'UiObject')
}
finalizeEventsServerClient()
thisObject.container.eventHandler.stopListening(selfFocusEventSubscriptionId)
thisObject.container.eventHandler.stopListening(selfNotFocusEventSubscriptionId)
@@ -173,6 +168,19 @@ function newUiObject () {
onRunningCallBackFunction = undefined
}
function finalizeEventsServerClient () {
if (eventsServerClient !== undefined) {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
if (eventSubscriptionIdOnRunning !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject')
}
if (eventSubscriptionIdOnStopped !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnStopped, 'UiObject')
}
}
}
function initialize (payload, menuItemsInitialValues) {
thisObject.payload = payload
@@ -257,7 +265,7 @@ function newUiObject () {
if (container !== undefined) { return container }
}
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
if (thisObject.container.frame.isThisPointHere(point, true, true) === true) {
return thisObject.container
} else {
return undefined
@@ -750,14 +758,17 @@ function newUiObject () {
}
}
function run (callBackFunction) {
function run (pEventsServerClient, callBackFunction) {
finalizeEventsServerClient()
eventsServerClient = pEventsServerClient
/* We setup the circular progress bar. */
if (thisObject.circularProgressBar !== undefined) {
thisObject.circularProgressBar.finalize()
}
thisObject.circularProgressBar = newCircularProgressBar()
thisObject.circularProgressBar.initialize(thisObject.payload)
thisObject.circularProgressBar.initialize(thisObject.payload, eventsServerClient)
thisObject.circularProgressBar.fitFunction = thisObject.fitFunction
thisObject.circularProgressBar.container = thisObject.container
@@ -1413,7 +1424,7 @@ function newUiObject () {
let label
if (radius > 6) {
const MAX_LABEL_LENGTH = 65
const MAX_LABEL_LENGTH = 100
label = currentStatus
+17 -6
View File
@@ -157,6 +157,17 @@ function newUiObjectConstructor () {
}
}
/* Default Values in case there was no way to set a value previous to this. */
if (floatingObject.angleToParent === undefined) {
floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_360
}
if (floatingObject.distanceToParent === undefined) {
floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_100X
}
if (floatingObject.arrangementStyle === undefined) {
floatingObject.arrangementStyle = ARRANGEMENT_STYLE.CONCAVE
}
let uiObject = newUiObject()
payload.uiObject = uiObject
uiObject.fitFunction = canvas.floatingSpace.fitIntoVisibleArea
@@ -243,7 +254,7 @@ function newUiObjectConstructor () {
)
menuItemsInitialValues.push(
{
action: 'change Distance to Paarent',
action: 'Change Distance to Paarent',
actionFunction: floatingObject.distanceToParentToggle,
actionStatus: floatingObject.getDistanceToParent,
currentStatus: true,
@@ -258,7 +269,7 @@ function newUiObjectConstructor () {
)
menuItemsInitialValues.push(
{
action: 'change Arrangement Style',
action: 'Change Arrangement Style',
actionFunction: floatingObject.arrangementStyleToggle,
actionStatus: floatingObject.getArrangementStyle,
currentStatus: true,
@@ -401,26 +412,26 @@ function newUiObjectConstructor () {
if (nodeDefinition.editors.config === true) {
uiObject.configEditor = newConfigEditor()
uiObject.configEditor.isVisibleFunction = uiObject.isVisibleFunction
uiObject.configEditor.initialize()
uiObject.configEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false)
uiObject.configEditor.initialize()
}
if (nodeDefinition.editors.code === true) {
uiObject.codeEditor = newCodeEditor()
uiObject.codeEditor.isVisibleFunction = uiObject.isVisibleFunction
uiObject.codeEditor.initialize()
uiObject.codeEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false)
uiObject.codeEditor.initialize()
}
if (nodeDefinition.editors.formula === true) {
uiObject.formulaEditor = newFormulaEditor()
uiObject.formulaEditor.isVisibleFunction = uiObject.isVisibleFunction
uiObject.formulaEditor.initialize()
uiObject.formulaEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false)
uiObject.formulaEditor.initialize()
}
if (nodeDefinition.editors.condition === true) {
uiObject.conditionEditor = newConditionEditor()
uiObject.conditionEditor.isVisibleFunction = uiObject.isVisibleFunction
uiObject.conditionEditor.container.connectToParent(uiObject.container, false, false, false, true, false, false, false, false)
uiObject.conditionEditor.initialize()
uiObject.conditionEditor.container.connectToParent(uiObject.container, false, false, true, true, false, false, false, false)
}
}
if (nodeDefinition.addLeftIcons === true) {
+1 -1
View File
@@ -211,7 +211,7 @@ function newFrame () {
/* Now we check if the resulting point is whin the current Frame. */
if (isNaN(checkPoint.x) || isNaN(checkPoint.y)) { return false }
if (thisObject.type === 'Circle') {
let distance = Math.sqrt(Math.pow(thisObject.position.x - point.x, 2) + Math.pow(thisObject.position.y - point.y, 2))
let distance = Math.sqrt(Math.pow(thisObject.position.x - checkPoint.x, 2) + Math.pow(thisObject.position.y - checkPoint.y, 2))
if (distance < thisObject.radius) {
return true
+16 -3
View File
@@ -20,6 +20,7 @@ function newLayer () {
plotterTypeIcon: undefined,
baseAssetIcon: undefined,
quotedAssetIcon: undefined,
networkNode: undefined,
checkStatusAtShutDown: checkStatusAtShutDown,
physics: physics,
draw: draw,
@@ -128,6 +129,7 @@ function newLayer () {
thisObject.plotterTypeIcon = undefined
thisObject.baseAssetIcon = undefined
thisObject.quotedAssetIcon = undefined
thisObject.networkNode = undefined
}
function initialize (callBackFunction) {
@@ -151,9 +153,10 @@ function newLayer () {
let functionLibraryProtocolNode = newProtocolNode()
let lightingPath =
'->Layer->' +
'Data Product->Single Market Data->' +
'Session Independent Data->Session Based Data->' +
'Session Reference->Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' +
'Data Product->Single Market Data->Exchange Data Products->' +
'Session Reference->Session Independent Data->Session Based Data->Exchange Sessions->Session Based Data->Data Storage->Network Node->' +
'Data Storage->Network Node->' +
'Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' +
'Market->Market Base Asset->Asset->' +
'Market Quoted Asset->Asset->' +
'Exchange Markets->Crypto Exchange->' +
@@ -186,6 +189,10 @@ function newLayer () {
if (thisObject.definition.referenceParent.referenceParent === undefined) { return }
if (thisObject.definition.referenceParent.referenceParent.parentNode === undefined) { return }
if (thisObject.definition.referenceParent.referenceParent.parentNode.parentNode === undefined) { return }
if (thisObject.definition.referenceParent.parentNode.parentNode === undefined) { return }
if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode === undefined) { return }
if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode === undefined) { return }
if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.parentNode === undefined) { return }
/* Lets listen to our own events to react when we have a Mouse Click */
onMouseClickEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
@@ -226,6 +233,12 @@ function newLayer () {
thisObject.baseAssetIcon = getIcon(thisObject.baseAsset)
thisObject.quotedAssetIcon = getIcon(thisObject.quotedAsset)
if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.type === 'Data Storage') {
thisObject.networkNode = thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.parentNode
} else {
thisObject.networkNode = thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode
}
function getIcon (node) {
let nodeDefinition = APP_SCHEMA_MAP.get(node.type)
let iconName
+1 -4
View File
@@ -1,6 +1,5 @@
let canvas
let markets
let eventsServerClient
let APP_SCHEMA_MAP = new Map()
let APP_SCHEMA_ARRAY = []
@@ -23,9 +22,7 @@ function newDashboard () {
function start () {
try {
setBrowserEvents()
eventsServerClient = newEventsServerClient()
eventsServerClient.initialize(setUpAppSchema)
setUpAppSchema()
function setUpAppSchema () {
APP_SCHEMA_ARRAY = getAppSchema()
+5 -5
View File
@@ -74,7 +74,7 @@ function newProductStorage (name) {
}
}
function initialize (dataMine, bot, session, product, exchange, market, pDatetime, pTimeFrame, callBackFunction) {
function initialize (dataMine, 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, onMarketFileReady)
marketFiles.initialize(dataMine, 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, onDailyFileReady)
dailyFiles.initialize(dataMine, 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, onSingleFileReady)
singleFile.initialize(dataMine, 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, onFileSequenceReady)
fileSequences.initialize(dataMine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onFileSequenceReady)
thisObject.fileSequences.push(fileSequences)
}
break
+1 -1
View File
@@ -122,7 +122,7 @@ function newSplashScreen () {
fontSize = 35
title = 'Beta'
title = 'Beta 4'
titlePoint = {
x: thisObject.container.frame.width / 2 - title.length / 2 * fontSize * FONT_ASPECT_RATIO - 20,
@@ -105,10 +105,11 @@ function roundedCornersBackground (params) {
browserCanvasContext.stroke()
}
function drawLabel (label, xFactor, yFactor, xOffset, yOffset, fontSize, container, fontColor, noFrameX, noFrameY) {
function drawLabel (label, xFactor, yFactor, xOffset, yOffset, fontSize, container, fontColor, noFrameX, noFrameY, opacity) {
if (label === undefined) { return }
if (fontColor === undefined) { fontColor = UI_COLOR.WHITE }
let fontOffset = label.length * fontSize * FONT_ASPECT_RATIO + 10
if (opacity === undefined) { opacity = 1 }
let labelPoint = {
x: container.frame.width * xFactor + xOffset - fontOffset / 2,
@@ -126,7 +127,7 @@ function drawLabel (label, xFactor, yFactor, xOffset, yOffset, fontSize, contain
}
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
browserCanvasContext.fillStyle = 'rgba(' + fontColor + ', 1)'
browserCanvasContext.fillStyle = 'rgba(' + fontColor + ', ' + opacity + ')'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
+1 -1
View File
@@ -1 +1 @@
{"type":"Data Mine","name":"Masters","code":"{\n\"codeName\": \"Masters\"\n}","sensorBots":[{"type":"Sensor Bot","name":"Exchange Raw Data","code":"{\n\"codeName\": \"Exchange-Raw-Data\",\n\"repo\": \"Exchange-Raw-Data-Sensor-Bot\"\n}","processes":[{"type":"Process Definition","name":"Historic-Trades","code":"{\n \"codeName\": \"Historic-Trades\",\n \"description\": \"Retrieves and saves the historical trades in batches going backwards from the current time until reaching the begining of the market.\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"e3008f15-43ae-4452-9c28-bfbb6c1a5e84","savedPayload":{"position":{"x":13889.892304785908,"y":17976.7326423862},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Self Reference","code":"{\n \"mainUtility\": \"Self Reference\"\n}","id":"f796022a-7871-4bde-bcc7-bcf2818f1eaf","savedPayload":{"position":{"x":14299.325525762739,"y":17993.12379366583},"targetPosition":{"x":13938.17907937083,"y":17993.12379366583},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235"}}}],"dataDependencies":[],"id":"1332b41e-7cd2-4e69-a40a-39ea47df67b5","savedPayload":{"position":{"x":13938.17907937083,"y":17993.12379366583},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235","savedPayload":{"position":{"x":13983.913279342734,"y":18015.677405195172},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"New Execution Started Event","id":"a9ea7169-fcd8-48c3-b0a9-b4e8941aa170","savedPayload":{"position":{"x":14026.312379860185,"y":18044.00757842793},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"51908884-c7a2-46ca-8a55-209070ae5fa6","savedPayload":{"position":{"x":14064.650920558077,"y":18077.62957624547},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"7a6a9399-474f-4a93-bcbd-28a594ef1943","savedPayload":{"position":{"x":14351.93363503598,"y":18425.400341491753},"targetPosition":{"x":13888.04337325749,"y":18696.024787447222},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Historic-OHLCVs","code":"{\n \"codeName\": \"Historic-OHLCVs\",\n \"description\": \"Retrieves and saves historical maket data\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"dfe2556e-a765-4e38-9d30-7f91090c0069","savedPayload":{"position":{"x":14546.018334597831,"y":18039.39680205973},"targetPosition":{"x":14407.127481538195,"y":18558.43550715096},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","code":"{\n \"mainUtility\": \"Self ReferencLine truncated
{"type":"Data Mine","name":"Masters","code":"{\n\"codeName\": \"Masters\"\n}","sensorBots":[{"type":"Sensor Bot","name":"Exchange Raw Data","code":"{\n\"codeName\": \"Exchange-Raw-Data\",\n\"repo\": \"Exchange-Raw-Data-Sensor-Bot\"\n}","processes":[{"type":"Process Definition","name":"Historic-Trades","code":"{\n \"codeName\": \"Historic-Trades\",\n \"description\": \"Retrieves and saves the historical trades in batches going backwards from the current time until reaching the begining of the market.\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"e3008f15-43ae-4452-9c28-bfbb6c1a5e84","savedPayload":{"position":{"x":13889.892304785908,"y":17976.7326423862},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Self Reference","code":"{\n \"mainUtility\": \"Self Reference\"\n}","id":"f796022a-7871-4bde-bcc7-bcf2818f1eaf","savedPayload":{"position":{"x":14299.325525762739,"y":17993.12379366583},"targetPosition":{"x":13938.17907937083,"y":17993.12379366583},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235"}}}],"dataDependencies":[],"id":"1332b41e-7cd2-4e69-a40a-39ea47df67b5","savedPayload":{"position":{"x":13938.17907937083,"y":17993.12379366583},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235","savedPayload":{"position":{"x":13983.913279342734,"y":18015.677405195172},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"New Execution Started Event","id":"a9ea7169-fcd8-48c3-b0a9-b4e8941aa170","savedPayload":{"position":{"x":14026.312379860185,"y":18044.00757842793},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"51908884-c7a2-46ca-8a55-209070ae5fa6","savedPayload":{"position":{"x":14064.650920558077,"y":18077.62957624547},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"7a6a9399-474f-4a93-bcbd-28a594ef1943","savedPayload":{"position":{"x":14351.93363503598,"y":18425.400341491753},"targetPosition":{"x":13888.04337325749,"y":18696.024787447222},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Historic-OHLCVs","code":"{\n \"codeName\": \"Historic-OHLCVs\",\n \"description\": \"Retrieves and saves historical maket data\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"dfe2556e-a765-4e38-9d30-7f91090c0069","savedPayload":{"position":{"x":14546.018334597831,"y":18039.39680205973},"targetPosition":{"x":14407.127481538195,"y":18558.43550715096},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","code":"{\n \"mainUtility\": \"Self ReferencLine truncated
+3 -3
View File
@@ -45,14 +45,14 @@ function newDailyFiles () {
}
}
function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pDatetime, pTimeFrame, callBackFunction) {
function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pDatetime, pTimeFrame, pHost, pPort, pEventsServerClient, callBackFunction) {
try {
callBackWhenFileReceived = callBackFunction
let exchange = pExchange
fileCloud = newFileCloud()
fileCloud.initialize(pBot)
fileCloud.initialize(pBot, pHost, pPort)
/* Some Validations */
if (pDataset.code.validTimeFrames === undefined) {
@@ -114,7 +114,7 @@ function newDailyFiles () {
if (pDataset.code.validTimeFrames.includes(periodName) === true) {
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, onInitialized)
fileCursor.initialize(fileCloud, pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, periodName, periodTime, pDatetime, pTimeFrame, beginDateRange, endDateRange, pEventsServerClient, onInitialized)
function onInitialized (err) {
try {
switch (err.result) {
+4 -4
View File
@@ -17,12 +17,12 @@ function newFileCloud () {
initialize: initialize
}
let blobService
let fileStorage
return thisObject
function initialize (pBot) {
blobService = newFileStorage()
function initialize (pBot, pHost, pPort) {
fileStorage = newFileStorage(pHost, pPort)
}
function getFile (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, callBackFunction) {
@@ -121,7 +121,7 @@ function newFileCloud () {
if (INFO_LOG === true) { logger.write('[INFO] getFile -> getFileRecursively -> filePath = ' + filePath) }
if (INFO_LOG === true) { logger.write('[INFO] getFile -> getFileRecursively -> fileName = ' + fileName) }
blobService.getBlobToText(filePath + '/' + fileName, undefined, onFileReceived)
fileStorage.getFileFromHost(filePath + '/' + fileName, onFileReceived)
function onFileReceived (err, text, response) {
try {
+20 -1
View File
@@ -34,6 +34,7 @@ function newFileCursor () {
let timeFrame
let beginDateRange
let endDateRange
let eventsServerClient
let finalized = false
@@ -61,6 +62,7 @@ function newFileCursor () {
timeFrame = undefined
beginDateRange = undefined
endDateRange = undefined
eventsServerClient = undefined
thisObject.files = undefined
cursorDate = undefined
@@ -73,7 +75,23 @@ function newFileCursor () {
}
}
function initialize (pFileCloud, pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pTimeFrame, pCursorDate, pCurrentTimeFrame, pBeginDateRange, pEndDateRange, callBackFunction) {
function initialize (
pFileCloud,
pDataMine,
pBot,
pSession,
pProduct,
pDataset,
pExchange,
pMarket,
pPeriodName,
pTimeFrame,
pCursorDate,
pCurrentTimeFrame,
pBeginDateRange,
pEndDateRange,
pEventsServerClient,
callBackFunction) {
try {
market = pMarket
exchange = pExchange
@@ -88,6 +106,7 @@ function newFileCursor () {
timeFrame = pTimeFrame
beginDateRange = pBeginDateRange
endDateRange = pEndDateRange
eventsServerClient = pEventsServerClient
let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
let callerId = key + '-' + periodName + newUniqueId()
+16 -2
View File
@@ -32,6 +32,7 @@ function newFileSequence () {
let eventSubscriptionIdDatasetUpdated
let callerId
let eventsServerClient
return thisObject
@@ -52,6 +53,7 @@ function newFileSequence () {
session = undefined
dataset = undefined
product = undefined
eventsServerClient = undefined
finalized = true
} catch (err) {
@@ -59,7 +61,18 @@ function newFileSequence () {
}
}
function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, callBackFunction) {
function initialize (
pDataMine,
pBot,
pSession,
pProduct,
pDataset,
pExchange,
pMarket,
pHost,
pPort,
pEventsServerClient,
callBackFunction) {
try {
exchange = pExchange
market = pMarket
@@ -68,9 +81,10 @@ function newFileSequence () {
session = pSession
dataset = pDataset
product = pProduct
eventsServerClient = pEventsServerClient
fileCloud = newFileCloud()
fileCloud.initialize(bot)
fileCloud.initialize(bot, pHost, pPort)
callerId = newUniqueId()
+14 -6
View File
@@ -1,4 +1,4 @@
function newFileStorage () {
function newFileStorage (host, port) {
const MODULE_NAME = 'File Storage'
const INFO_LOG = false
const logger = newWebDebugLog()
@@ -24,20 +24,28 @@ function newFileStorage () {
]
let thisObject = {
getBlobToText: getBlobToText
getFileFromHost: getFileFromHost
}
if (host === '' || host === undefined) { host = 'localhost' }
if (port === '' || port === undefined) { port = '34247' }
return thisObject
async function getBlobToText (filePath, host, callBackFunction, pathComplete) {
async function getFileFromHost (filePath, callBackFunction, pathComplete) {
try {
if (INFO_LOG === true) { logger.write('[INFO] getBlobToText -> Entering function.') }
if (INFO_LOG === true) { logger.write('[INFO] getFileFromHost -> Entering function.') }
let folder = ''
if (pathComplete === false || pathComplete === undefined) {
folder = 'Storage/'
}
callServer(undefined, folder + filePath, (response, fileContent) => {
let url = folder + filePath
if (host !== undefined) {
url = 'http://' + host + ':' + port + '/' + folder + filePath
}
callServer(undefined, url, (response, fileContent) => {
if (response.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, fileContent)
} else {
@@ -48,7 +56,7 @@ function newFileStorage () {
if (verifyRetry(err.code) && currentRetry < MAX_RETRY) {
currentRetry++
if (INFO_LOG === true) { console.log('[INFO] getTextFile -> Retrying connection to the server because received error: ' + err.code + '. Retry #: ' + currentRetry) }
getBlobToText(filePath, host, callBackFunction)
getFileFromHost(filePath, callBackFunction)
} else if (err.message === 'Request aborted') {
let err = { code: 'The specified key does not exist.' }
callBackFunction(err)
+16 -2
View File
@@ -37,6 +37,7 @@ function newMarketFiles () {
let finalized = false
let eventSubscriptionIdDatasetUpdated = []
let eventsServerClient
return thisObject
@@ -60,6 +61,7 @@ function newMarketFiles () {
dataset = undefined
product = undefined
periodName = undefined
eventsServerClient = undefined
finalized = true
} catch (err) {
@@ -67,7 +69,18 @@ function newMarketFiles () {
}
}
function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, callBackFunction) {
function initialize (
pDataMine,
pBot,
pSession,
pProduct,
pDataset,
pExchange,
pMarket,
pHost,
pPort,
pEventsServerClient,
callBackFunction) {
try {
exchange = pExchange
market = pMarket
@@ -76,9 +89,10 @@ function newMarketFiles () {
session = pSession
dataset = pDataset
product = pProduct
eventsServerClient = pEventsServerClient
fileCloud = newFileCloud()
fileCloud.initialize(pBot)
fileCloud.initialize(pBot, pHost, pPort)
/* Some Validations */
if (dataset.code.validTimeFrames === undefined) {
+13 -2
View File
@@ -16,7 +16,18 @@ function newSingleFile () {
return thisObject
function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, callBackFunction) {
function initialize (
pDataMine,
pBot,
pSession,
pProduct,
pDataset,
pExchange,
pMarket,
pHost,
pPort,
pEventsServerClient,
callBackFunction) {
try {
if (INFO_LOG === true) { logger.write('[INFO] initialize -> Entering function.') }
if (INFO_LOG === true) { logger.write('[INFO] initialize -> key = ' + pDataMine.code.codeName + '-' + pBot.code.codeName + '-' + pProduct.code.codeName) }
@@ -24,7 +35,7 @@ function newSingleFile () {
let exchange = pExchange
fileCloud = newFileCloud()
fileCloud.initialize(pBot)
fileCloud.initialize(pBot, pHost, pPort)
/* Now we will get the file */
@@ -385,8 +385,10 @@
record.maximunBalanceB = dailyFile[i][32];
record.baseAsset = dailyFile[i][33];
record.quotedAsset = dailyFile[i][34];
record.positionPeriods = dailyFile[i][35];
record.positionDays = dailyFile[i][36];
record.marketBaseAsset = dailyFile[i][35];
record.marketQuotedAsset = dailyFile[i][36];
record.positionPeriods = dailyFile[i][37];
record.positionDays = dailyFile[i][38];
if (
(record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) &&
@@ -477,8 +479,10 @@
record.maximunBalanceB = marketFile[i][32];
record.baseAsset = marketFile[i][33];
record.quotedAsset = marketFile[i][34];
record.positionPeriods = marketFile[i][35];
record.positionDays = marketFile[i][36];
record.marketBaseAsset = marketFile[i][35];
record.marketQuotedAsset = marketFile[i][36];
record.positionPeriods = marketFile[i][37];
record.positionDays = marketFile[i][38];
if (
(record.begin >= leftDate.valueOf() && record.end <= rightDate.valueOf()) &&
@@ -154,33 +154,64 @@ function newTradingEnginesPlottersTradingSimulationTradingSimulationTradingSimul
return
}
params = {}
params.VALUE = currentRecord.balanceA;
params.INIT_VALUE = currentRecord.initialBalanceA
params.MIN_VALUE = currentRecord.minimunBalanceA
params.MAX_VALUE = currentRecord.maximunBalanceA
params.ASSET_LABEL = 'Asset A'
params.ASSET_NAME = currentRecord.baseAsset
params.LEFT_OFFSET = X_AXIS
params.POSITION_TAKEN = positionTaken
params.BASE_ASSET = currentRecord.baseAsset
params.DECIMALS = 4
if (currentRecord.baseAsset === currentRecord.marketBaseAsset) {
params = {}
params.VALUE = currentRecord.balanceA;
params.INIT_VALUE = currentRecord.initialBalanceA
params.MIN_VALUE = currentRecord.minimunBalanceA
params.MAX_VALUE = currentRecord.maximunBalanceA
params.ASSET_LABEL = 'Base'
params.ASSET_NAME = currentRecord.baseAsset
params.LEFT_OFFSET = X_AXIS
params.POSITION_TAKEN = positionTaken
params.BASE_ASSET = currentRecord.baseAsset
params.DECIMALS = 4
paramsArray.push(params)
paramsArray.push(params)
params = {}
params.VALUE = currentRecord.balanceB;
params.MIN_VALUE = currentRecord.minimunBalanceB
params.INIT_VALUE = currentRecord.initialBalanceB
params.MAX_VALUE = currentRecord.maximunBalanceB
params.ASSET_LABEL = 'Asset B'
params.ASSET_NAME = currentRecord.quotedAsset
params.LEFT_OFFSET = X_AXIS
params.POSITION_TAKEN = positionTaken
params.BASE_ASSET = currentRecord.baseAsset
params.DECIMALS = 2
params = {}
params.VALUE = currentRecord.balanceB;
params.MIN_VALUE = currentRecord.minimunBalanceB
params.INIT_VALUE = currentRecord.initialBalanceB
params.MAX_VALUE = currentRecord.maximunBalanceB
params.ASSET_LABEL = 'Quoted'
params.ASSET_NAME = currentRecord.quotedAsset
params.LEFT_OFFSET = X_AXIS
params.POSITION_TAKEN = positionTaken
params.BASE_ASSET = currentRecord.baseAsset
params.DECIMALS = 2
paramsArray.push(params)
} else {
params = {}
params.VALUE = currentRecord.balanceB;
params.INIT_VALUE = currentRecord.initialBalanceB
params.MIN_VALUE = currentRecord.minimunBalanceB
params.MAX_VALUE = currentRecord.maximunBalanceB
params.ASSET_LABEL = 'Base'
params.ASSET_NAME = currentRecord.baseAsset
params.LEFT_OFFSET = X_AXIS
params.POSITION_TAKEN = positionTaken
params.BASE_ASSET = currentRecord.baseAsset
params.DECIMALS = 4
paramsArray.push(params)
params = {}
params.VALUE = currentRecord.balanceA;
params.MIN_VALUE = currentRecord.minimunBalanceA
params.INIT_VALUE = currentRecord.initialBalanceA
params.MAX_VALUE = currentRecord.maximunBalanceA
params.ASSET_LABEL = 'Quoted'
params.ASSET_NAME = currentRecord.quotedAsset
params.LEFT_OFFSET = X_AXIS
params.POSITION_TAKEN = positionTaken
params.BASE_ASSET = currentRecord.baseAsset
params.DECIMALS = 2
paramsArray.push(params)
}
paramsArray.push(params)
thisObject.assetBalances.setParamsArray(paramsArray)
thisObject.assetBalances.draw()
+4
View File
@@ -1,3 +1,7 @@
# Contact Us
Please join our Telegram Community to contact us there: https://t.me/superalgoscommunity
# Superalgos
Superalgos provides a toolbox with many integrated tools that could help you research crypto markets and design / automate trading strategies. You can use Superalgos to download market data from crypto exchanges, make arbitrary calculations with it (including indicators), plot the results of your calculations, design, test and automate trading strategies, and more.
+1
View File
@@ -0,0 +1 @@
{"type":"Workspace","name":"Simple Workspace","rootNodes":[{"type":"Network","name":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","code":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34247\", \n\"webSocketsPort\": \"8080\"\n}","dataStorage":{"type":"Data Storage","name":"New Data Storage","sessionIndependentData":{"type":"Session Independent Data","name":"New Session Independent Data","exchangeDataProducts":[{"type":"Exchange Data Products","name":"New Exchange Data Products","singleMarketData":[{"type":"Single Market Data","name":"","dataProducts":[{"type":"Data Product","name":"Candles","id":"cc7f62f2-0aa8-498c-861c-85060dd70522","savedPayload":{"position":{"x":39641.333811210454,"y":28936.98413868935},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"70e3b1ab-65d9-4c9e-8489-35d6852e7ef5","savedPayload":{"position":{"x":39612.59634583407,"y":28848.5110343909},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"eebb207f-6a7e-405a-9bed-2ff3afdd12af","savedPayload":{"position":{"x":39594.15352768551,"y":28758.904338266497},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"09706013-dc8f-4e40-8a71-129191aa521d","savedPayload":{"position":{"x":39585.513470979095,"y":28668.600155855387},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"d81b957c-4a39-4c15-8158-c05a0e63e591","savedPayload":{"position":{"x":39586.515890435076,"y":28578.275802249987},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"dd2bbd8b-0c18-4cc2-b176-ad3b177a98a7","savedPayload":{"position":{"x":39597.01323868843,"y":28488.759535006342},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"c2f6e67c-b1b1-47d3-9600-cf18be037620","savedPayload":{"position":{"x":39616.82107043368,"y":28400.936525998834},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"074c15c8-317c-4358-963f-4186f245bb25","savedPayload":{"position":{"x":39645.70528040039,"y":28315.720626172813},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"c4a5297a-6f84-4337-8cd8-4ebde8fa1ae5","savedPayload":{"position":{"x":39683.34058679891,"y":28234.020419812852},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollaLine truncated
+1 -1
View File
@@ -1 +1 @@
{"type":"Super Scripts","name":"Masters","code":"{ \n\"codeName\": \"Masters\"\n}","scriptsLibrary":{"type":"Scripts Library","name":"New Scripts Library","masterScripts":[{"type":"Master Script","name":"Setup Market","templateScripts":[{"type":"Template Script","name":"Install Single Market Data","templateStructure":{"type":"Template Structure","name":"New Template Structure","singleMarketData":{"type":"Single Market Data","name":"","dataProducts":[{"type":"Data Product","name":"Candles","id":"24c5f795-acf3-43c3-99ee-ddb521b082f4","savedPayload":{"position":{"x":39933.49393163037,"y":29046.10981068428},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"204ec959-0861-486a-aa2a-276dbf48f775","savedPayload":{"position":{"x":39908.11948414529,"y":28963.262354549173},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"90ee9733-ab7e-41a0-ac78-4a7661a27017","savedPayload":{"position":{"x":39895.18349066973,"y":28880.38336833146},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"9ade8e93-9071-422b-8cce-7a50d6dad739","savedPayload":{"position":{"x":39893.27964669049,"y":28797.90081457585},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"b5ef2cf7-3d35-45ec-848c-31970b59c04e","savedPayload":{"position":{"x":39901.90265885927,"y":28716.54731001258},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"1c3881ca-24b3-4cc9-b16b-9db7aa2b4c24","savedPayload":{"position":{"x":39920.664403351046,"y":28637.27326471363},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"92eec33b-86be-4b73-899f-e9550f7b0df3","savedPayload":{"position":{"x":39949.20152839712,"y":28561.15482568263},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"4b69df71-9091-4d22-9b0d-571304297033","savedPayload":{"position":{"x":39987.032994167246,"y":28489.298406726437},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"8a5f7e27-9ca5-4d6e-b6b9-2d6cbdda8040","savedPayload":{"position":{"x":40033.55648252736,"y":28422.790182572182},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"tLine truncated
{"type":"Super Scripts","name":"Masters","code":"{ \n\"codeName\": \"Masters\"\n}","scriptsLibrary":{"type":"Scripts Library","name":"New Scripts Library","masterScripts":[{"type":"Master Script","name":"Setup Market","templateScripts":[{"type":"Template Script","name":"Install Single Market Data","templateStructure":{"type":"Template Structure","name":"New Template Structure","singleMarketData":{"type":"Single Market Data","name":"","dataProducts":[{"type":"Data Product","name":"Candles","id":"24c5f795-acf3-43c3-99ee-ddb521b082f4","savedPayload":{"position":{"x":39641.333811210454,"y":28936.98413868935},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"204ec959-0861-486a-aa2a-276dbf48f775","savedPayload":{"position":{"x":39612.59634583407,"y":28848.5110343909},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"90ee9733-ab7e-41a0-ac78-4a7661a27017","savedPayload":{"position":{"x":39594.15352768551,"y":28758.904338266497},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"9ade8e93-9071-422b-8cce-7a50d6dad739","savedPayload":{"position":{"x":39585.513470979095,"y":28668.600155855387},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"b5ef2cf7-3d35-45ec-848c-31970b59c04e","savedPayload":{"position":{"x":39586.515890435076,"y":28578.275802249987},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"1c3881ca-24b3-4cc9-b16b-9db7aa2b4c24","savedPayload":{"position":{"x":39597.01323868843,"y":28488.759535006342},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"92eec33b-86be-4b73-899f-e9550f7b0df3","savedPayload":{"position":{"x":39616.82107043368,"y":28400.936525998834},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"4b69df71-9091-4d22-9b0d-571304297033","savedPayload":{"position":{"x":39645.70528040039,"y":28315.720626172813},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"8a5f7e27-9ca5-4d6e-b6b9-2d6cbdda8040","savedPayload":{"position":{"x":39683.34058679891,"y":28234.020419812852},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":Line truncated
+13 -2
View File
@@ -10,7 +10,8 @@
nodeArray: undefined,
dataSetsModulesArray: [],
isItADepenency: isItADepenency,
initialize: initialize
initialize: initialize,
finalize: finalize
};
let filter = new Map()
@@ -69,7 +70,7 @@
function onInitilized(err) {
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> err = "+ err.stack);
logger.write(MODULE_NAME, "[ERROR] initialize -> onInitilized -> err = "+ JSON.stringify(err));
alreadyCalledBack = true;
callBackFunction(err);
@@ -103,6 +104,16 @@
}
}
function finalize() {
for (let i = 0; i < thisObject.dataSetsModulesArray.length; i++) {
let dataSetModule = thisObject.dataSetsModulesArray[i]
dataSetModule.finalize()
}
thisObject.dataSetsModulesArray = undefined
filter = undefined
bot = undefined
}
function isItADepenency(timeFrame, product) {
let key = timeFrame + '-' + product
+85 -2
View File
@@ -6,7 +6,9 @@ exports.newDataSet = function newDataSet(BOT, logger) {
let thisObject = {
node: undefined,
networkNode: undefined,
initialize: initialize,
finalize: finalize,
getTextFile: getTextFile,
createTextFile: createTextFile
};
@@ -14,7 +16,7 @@ exports.newDataSet = function newDataSet(BOT, logger) {
/* Storage account to be used here. */
const FILE_STORAGE = require('./FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage(logger);
let fileStorage
return thisObject;
@@ -76,7 +78,81 @@ exports.newDataSet = function newDataSet(BOT, logger) {
return
}
callBackFunction(global.DEFAULT_OK_RESPONSE);
/* Now we will see where do we need to fetch this data from. */
let network = global.TASK_NETWORK
let datasetProductDefinition = thisObject.node.parentNode
for (let i = 0; i < network.networkNodes.length; i++) {
let networkNode = network.networkNodes[i]
if (networkNode.dataStorage !== undefined) {
if (networkNode.dataStorage.sessionIndependentData !== undefined) {
for (let j = 0; j < networkNode.dataStorage.sessionIndependentData.exchangeDataProducts.length; j++) {
let exchangeDataProduct = networkNode.dataStorage.sessionIndependentData.exchangeDataProducts[j]
for (let k = 0; k < exchangeDataProduct.singleMarketData.length; k++) {
let singleMarketData = exchangeDataProduct.singleMarketData[k]
if (singleMarketData.referenceParent !== undefined) {
let market = singleMarketData.referenceParent
let currentProcessMarket = bot.processNode.marketReference.referenceParent
if (currentProcessMarket.id === market.id) {
for (let m = 0; m < singleMarketData.dataProducts.length; m++) {
let dataProduct = singleMarketData.dataProducts[m]
if (dataProduct.referenceParent !== undefined) {
let productDefinition = dataProduct.referenceParent
if (datasetProductDefinition.id === productDefinition.id) {
/* We found where the data is located on the network. */
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving data from " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webPort + '.'); }
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.code.host, networkNode.code.webPort);
callBackFunction(global.DEFAULT_OK_RESPONSE);
return
}
}
}
}
}
}
}
}
if (networkNode.dataStorage.sessionBasedData !== undefined) {
for (let j = 0; j < networkNode.dataStorage.sessionBasedData.exchangeDataProducts.length; j++) {
let exchangeDataProduct = networkNode.dataStorage.sessionBasedData.exchangeDataProducts[j]
for (let s = 0; s < exchangeDataProduct.sessionReferences.length; s++) {
let sessionReference = exchangeDataProduct.sessionReferences[s]
let singleMarketData = sessionReference.singleMarketData
if (singleMarketData.referenceParent !== undefined) {
let market = singleMarketData.referenceParent
let currentProcessMarket = bot.processNode.marketReference.referenceParent
if (currentProcessMarket.id === market.id) {
for (let m = 0; m < singleMarketData.dataProducts.length; m++) {
let dataProduct = singleMarketData.dataProducts[m]
if (dataProduct.referenceParent !== undefined) {
let productDefinition = dataProduct.referenceParent
if (datasetProductDefinition.id === productDefinition.id) {
/* We found where the data is located on the network. */
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving data from " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webPort + '.'); }
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.code.host, networkNode.code.webPort);
callBackFunction(global.DEFAULT_OK_RESPONSE);
return
}
}
}
}
}
}
}
}
}
}
logger.write(MODULE_NAME, "[ERROR] initialize -> Initialization Failed because we could not find where the data of this dataset is located within the network. Check the logs for more info.");
logger.write(MODULE_NAME, "[ERROR] initialize -> Could not find where " + datasetProductDefinition.name + " for " + bot.exchange + " " + bot.market.baseAsset + "/" + bot.market.quotedAsset + " is stored within the network.");
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
@@ -84,6 +160,13 @@ exports.newDataSet = function newDataSet(BOT, logger) {
}
}
function finalize() {
fileStorage = undefined
thisObject.networkNode = undefined
bot = undefined
thisObject = undefined
}
function getTextFile(pFolderPath, pFileName, callBackFunction) {
try {
+7 -1
View File
@@ -17,7 +17,8 @@ exports.newDebugLog = function newDebugLog() {
write: write,
newInternalLoop: newInternalLoop,
persist: persist, // This method is executed at the end of each Main Loop.
initialize: initialize
initialize: initialize,
finalize: finalize
};
let accumulatedLog = "[";
@@ -37,6 +38,10 @@ exports.newDebugLog = function newDebugLog() {
}
}
function finalize() {
persist()
}
function newInternalLoop(pBot, pProcess, date, percentage) {
if (percentage === undefined) {
percentage = ""
@@ -64,6 +69,7 @@ exports.newDebugLog = function newDebugLog() {
/* Here we actually write the content of the in-memory log to a file */
try {
if (accumulatedLog === "[") {return} // nothing to persist at the moment.
internalLoopCounter++;
+10 -3
View File
@@ -1,4 +1,4 @@
exports.newEventsServerClient = function newEventsServerClient() {
exports.newEventsServerClient = function newEventsServerClient(host, port) {
const MODULE = "Task Server "
const ERROR_LOG = true
@@ -19,7 +19,14 @@
let WEB_SOCKETS_CLIENT
const WEB_SOCKET = require('ws')
let port = process.env.WEB_SOCKETS_SERVER_PORT
if (host === undefined) {
host = 'localhost'
}
if (port === undefined) {
port = process.env.WEB_SOCKETS_SERVER_PORT
}
return thisObject
@@ -32,7 +39,7 @@
function setuptWebSockets(callBackFunction) {
try {
WEB_SOCKETS_CLIENT = new WEB_SOCKET('ws://localhost:' + port )
WEB_SOCKETS_CLIENT = new WEB_SOCKET('ws://' + host + ':' + port )
WEB_SOCKETS_CLIENT.onerror = error => {
console.log('[ERROR] Task Server -> Event Server Client -> setuptWebSockets -> On connection error -> error = ' + JSON.stringify(error))
+1 -1
View File
@@ -38,7 +38,7 @@
'secret': secret,
'timeout': 30000,
'enableRateLimit': true,
verbose: true,
verbose: false,
options: options
}
+80 -9
View File
@@ -1,7 +1,7 @@
const path = require('path')
exports.newFileStorage = function newFileStorage(logger) {
exports.newFileStorage = function newFileStorage(logger, host, port) {
const MODULE_NAME = 'FileStorage'
const MAX_RETRY = 30
@@ -51,9 +51,15 @@ exports.newFileStorage = function newFileStorage(logger) {
logger.write(MODULE_NAME, '[INFO] FileStorage -> getTextFile -> fileLocation: ' + fileLocation)
/* Here we actually write the file. */
const fs = require('fs')
fs.readFile(fileLocation, onFileRead)
/* Here we actually reaad the file. */
if (host === undefined || host === 'localhost') {
/* We read the file from the local file system. */
const fs = require('fs')
fs.readFile(fileLocation, onFileRead)
} else {
/* We read the file via a web server over http */
getFileViaHTTP(fileLocation, onFileRead, callBackFunction)
}
function onFileRead(err, text) {
let retryTimeToUse = FAST_RETRY_TIME_IN_MILISECONDS
@@ -118,7 +124,14 @@ exports.newFileStorage = function newFileStorage(logger) {
if (canUsePrevious === true) {
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> onFileRead -> Could read the file, but could not parse it as it is not a valid JSON. Will try to read the PREVIOUS version instead. -> file = ' + fileLocation)
fs.readFile(fileLocation + '.Previous.json', onPreviousFileRead)
if (host === undefined || host === 'localhost') {
/* We read the file from the local file system. */
const fs = require('fs')
fs.readFile(fileLocation + '.Previous.json', onPreviousFileRead)
} else {
/* We read the file via a web server over http */
getFileViaHTTP(fileLocation + '.Previous.json', onPreviousFileRead, callBackFunction)
}
function onPreviousFileRead(err, text) {
@@ -136,6 +149,7 @@ exports.newFileStorage = function newFileStorage(logger) {
} else {
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> onFileRead -> Could read the file, but could not parse it as it is not a valid JSON.')
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> onFileRead -> err = ' + err.stack)
logger.write(MODULE_NAME, '[WARN] FileStorage -> getTextFile -> onFileRead -> text.toString() = ' + text.toString())
setTimeout(retry, retryTimeToUse)
return
}
@@ -390,9 +404,8 @@ exports.newFileStorage = function newFileStorage(logger) {
}
}
/* Function to create folders of missing folders at any path. */
function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
/* Function to create folders of missing folders at any path. */
function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
const sep = '/';
const initDir = path.isAbsolute(targetDir) ? sep : '';
const baseDir = isRelativeToScript ? __dirname : '.';
@@ -420,5 +433,63 @@ exports.newFileStorage = function newFileStorage(logger) {
return curDir;
}, initDir);
}
}
function getFileViaHTTP(filePath, callback, callBackFunction) {
try {
/* The filePath received is the one that is needed to fetch data from with fs. To do it via http we need to remove the prefix that includes this: ./Data-Storage/ */
filePath = filePath.substring(15, filePath.length)
let http = require('http');
let url = 'http://' + host +
':' + port +
'/Storage/' +
filePath
logger.write(MODULE_NAME, '[INFO] FileStorage -> getFileViaHTTP -> url = ' + url)
let request = http.get(url, onResponse);
request.on('error', function (err) {
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> onError -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> onError -> Failed to fetch file via HTTP. Will retry later. ");
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
})
function onResponse(response) {
try {
const chunks = []
response.on('data', onMessegesArrived)
response.on('end', onEnd)
function onMessegesArrived(chunk) {
chunks.push(chunk)
}
function onEnd() {
let fileContent = Buffer.concat(chunks).toString('utf8')
let err = null
if (fileContent.indexOf('does not exist') >= 0) {
err = {
code: "ENOENT" // This is how fs would have returned upon this situation.
}
fileContent = undefined
}
callback(err, fileContent)
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> onResponse -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> onResponse -> Failed to fetch file via HTTP. Will retry later. ");
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> err = " + err.stack);
logger.write(MODULE_NAME, "[ERROR] getFileViaHTTP -> Failed to fetch file via HTTP. Will retry later. ");
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
}
}
}
+17 -3
View File
@@ -116,7 +116,11 @@
/* 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();
@@ -252,6 +256,12 @@
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;
}
@@ -776,10 +786,13 @@
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Entering function."); }
processFramework.finalize()
processFramework = undefined
dataDependencies.finalize()
dataDependencies = undefined
statusDependencies.finalize()
statusDependencies = undefined
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
@@ -876,11 +889,12 @@
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); }
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.");
+1 -1
View File
@@ -124,7 +124,7 @@
thisReport = statusReport.file;
if (thisReport.lastFile === undefined) {
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey);
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> thisReport = " + JSON.stringify(thisReport));
let customOK = {
result: global.CUSTOM_OK_RESPONSE.result,
+99 -19
View File
@@ -8,57 +8,137 @@
*/
const MODULE_NAME = "Process Execution Events";
logger.fileName = MODULE_NAME
let bot = BOT;
let thisObject = {
networkNode: undefined,
initialize, initialize,
finalize: finalize,
start: start,
finish: finish
};
let processThisDependsOn; // This is the process this process needs to wait for it to finishes in order to start.
let currentProcessKey
let EVENT_SERVER_CLIENT = require('./EventServerClient.js');
let eventServerClient
return thisObject;
function initialize(callBackFunction) {
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
let name = 'Not Depends on any Process'
logger.fileName = MODULE_NAME + "." + name;
if (bot.processNode.referenceParent !== undefined) {
if (bot.processNode.referenceParent === undefined) {
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
logger.write(MODULE_NAME, "[ERROR] initialize -> Initialization Failed because the Process Instance needs to have a Reference Parent.");
return
}
let market = bot.market.baseAsset + '/' + bot.market.quotedAsset
currentProcessKey = bot.processNode.referenceParent.name + "-" + bot.processNode.referenceParent.type + "-" + bot.processNode.referenceParent.id + "-" + bot.exchange + "-" + market
let market = bot.market.baseAsset + '/' + bot.market.quotedAsset
currentProcessKey = bot.processNode.referenceParent.name + "-" + bot.processNode.referenceParent.type + "-" + bot.processNode.referenceParent.id + "-" + bot.exchange + "-" + market
if (bot.processNode.referenceParent.executionStartedEvent !== undefined) {
if (bot.processNode.referenceParent.executionStartedEvent.referenceParent !== undefined) {
if (bot.processNode.referenceParent.executionStartedEvent.referenceParent.parentNode !== undefined) {
processThisDependsOn = bot.processNode.referenceParent.executionStartedEvent.referenceParent.parentNode
if (bot.processNode.referenceParent.executionStartedEvent !== undefined) {
if (bot.processNode.referenceParent.executionStartedEvent.referenceParent !== undefined) {
if (bot.processNode.referenceParent.executionStartedEvent.referenceParent.parentNode !== undefined) {
processThisDependsOn = bot.processNode.referenceParent.executionStartedEvent.referenceParent.parentNode
name = processThisDependsOn.name
if (processThisDependsOn.code.monthlyInstances === true) {
logger.fileName = MODULE_NAME + "." + name;
}
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> " + currentProcessKey + " depends on " + name); }
name = processThisDependsOn.name
if (processThisDependsOn.code.monthlyInstances === true) {
logger.fileName = MODULE_NAME + "." + name;
}
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> " + currentProcessKey + " depends on " + name); }
}
}
}
logger.fileName = MODULE_NAME + "." + name;
callBackFunction(global.DEFAULT_OK_RESPONSE);
if (processThisDependsOn !== undefined) {
/* We need to find at which network node is running the process that we need to hear from when it finished. */
let network = global.TASK_NETWORK
for (let i = 0; i < network.networkNodes.length; i++) {
let networkNode = network.networkNodes[i]
if (networkNode.dataMining !== undefined) {
for (let j = 0; j < networkNode.dataMining.exchangeTasks.length; j++) {
let exchangeTasks = networkNode.dataMining.exchangeTasks[j]
for (let k = 0; k < exchangeTasks.taskManagers.length; k++) {
let taskManager = exchangeTasks.taskManagers[k]
for (let m = 0; m < taskManager.tasks.length; m++) {
let task = taskManager.tasks[m]
if (task.bot !== undefined) {
for (let n = 0; n < task.bot.processes.length; n++) {
let process = task.bot.processes[n]
if (process.marketReference !== undefined) {
if (process.marketReference.referenceParent !== undefined) {
let market = process.marketReference.referenceParent
let currentProcessMarket = bot.processNode.marketReference.referenceParent
if (currentProcessMarket.id === market.id) {
if (process.referenceParent !== undefined) {
let processDefinition = process.referenceParent
if (processThisDependsOn.id === processDefinition.id) {
/* We found where the task that runs the process definition we are waiting for is located on the network. */
thisObject.networkNode = networkNode
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Connecting to Websockets Server " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webSocketsPort + '.'); }
eventServerClient = EVENT_SERVER_CLIENT.newEventsServerClient(networkNode.code.host, networkNode.code.webSocketsPort)
eventServerClient.initialize(onConnected)
function onConnected() {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Connected to Websockets Server " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webSocketsPort + '.'); }
callBackFunction(global.DEFAULT_OK_RESPONSE);
return
}
return
}
}
}
}
}
}
}
}
}
}
}
}
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
logger.write(MODULE_NAME, "[ERROR] initialize -> Initialization Failed because we could not find where the task that runs the Process Definition we are waiting for is located within the network. Check the logs for more info.");
return
}
callBackFunction(global.DEFAULT_OK_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
function finalize() {
if (eventServerClient !== undefined) {
eventServerClient.finalize()
eventServerClient = undefined
}
processThisDependsOn = undefined
currentProcessKey = undefined
thisObject.networkNode = undefined
bot = undefined
thisObject = undefined
}
function start(callBackFunction) {
try {
@@ -81,9 +161,9 @@
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> waitForDependantProcess -> key = " + key); }
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> waitForDependantProcess -> callerId = " + callerId); }
global.EVENT_SERVER_CLIENT.listenToEvent(key, 'Process Execution Finished', undefined, callerId, responseCallBack, eventsCallBack)
eventServerClient.listenToEvent(key, 'Process Execution Finished', undefined, callerId, responseCallBack, eventsCallBack)
bot.processHeartBeat(undefined, undefined, "Waiting for " + processThisDependsOn.parentNode.parentNode.name + "->" + processThisDependsOn.parentNode.code.codeName + "->" + processThisDependsOn.code.codeName)
bot.processHeartBeat(undefined, undefined, "Waiting for " + thisObject.networkNode.name + "->" + processThisDependsOn.parentNode.parentNode.name + "->" + processThisDependsOn.parentNode.code.codeName + "->" + processThisDependsOn.code.codeName)
function responseCallBack(message) {
if (message.result !== global.DEFAULT_OK_RESPONSE.result) {
@@ -102,7 +182,7 @@
/* We continue the normal flow after we learn the dependent process has finished its execution. */
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> stopListening to Process Execution Finished. "); }
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] start -> eventsCallBack -> subscriptionId = " + subscriptionId); }
global.EVENT_SERVER_CLIENT.stopListening(key, 'Process Execution Finished', subscriptionId)
eventServerClient.stopListening(key, 'Process Execution Finished', subscriptionId)
if (message.event.err.result === global.DEFAULT_OK_RESPONSE.result) {
/* We emit our own event that the process started. */
+3
View File
@@ -391,6 +391,7 @@
let logger;
logger = DEBUG_MODULE.newDebugLog();
global.LOGGER_MAP.set('runSensorBot', logger)
logger.bot = pBotConfig;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runSensorBot -> Entering function."); }
@@ -455,6 +456,7 @@
let logger;
logger = DEBUG_MODULE.newDebugLog();
global.LOGGER_MAP.set('runIndicatorBot', logger)
logger.bot = pBotConfig;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> Entering function."); }
@@ -517,6 +519,7 @@
let logger;
logger = DEBUG_MODULE.newDebugLog();
global.LOGGER_MAP.set('runTradingBot', logger)
logger.bot = pBotConfig;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runTradingBot -> Entering function."); }
+13 -2
View File
@@ -121,7 +121,11 @@
/* 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();
@@ -254,6 +258,12 @@
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;
}
@@ -584,11 +594,12 @@
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); }
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.");
+1
View File
@@ -39,6 +39,7 @@
/* Listen to event to start or stop the session. */
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, 'Run Session', undefined, bot.sessionKey, undefined, runSession)
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Stop Session', undefined, bot.sessionKey, undefined, stopSession)
+10
View File
@@ -11,6 +11,7 @@
statusReports: new Map(),
reportsByMainUtility: new Map(),
initialize: initialize,
finalize: finalize,
keys: []
};
@@ -165,4 +166,13 @@
}
}
function finalize() {
thisObject.statusReports.forEach(forEachStatusDependency)
function forEachStatusDependency(statusDependency) {
statusDependency.finalize()
}
thisObject.statusReports = undefined
bot = undefined
thisObject = undefined
}
};
+79 -13
View File
@@ -13,9 +13,11 @@
let bot = BOT;
let thisObject = {
networkNode: undefined,
mainUtility: undefined,
file: undefined, // Here we have the JSON object representing the file content.
initialize: initialize,
finalize: finalize,
load: load,
save: save,
status: undefined
@@ -30,7 +32,7 @@
/* Storage account to be used here. */
const FILE_STORAGE = require('./FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage(logger);
let fileStorage
let sessionPath = ''
@@ -93,17 +95,6 @@
statusDependencyNode.bottype = statusDependencyNode.referenceParent.parentNode.parentNode.type
statusDependencyNode.dataMine = statusDependencyNode.referenceParent.parentNode.parentNode.parentNode.code.codeName
/* Let's see if the process is run monthly or not. */
if (statusDependencyNode.referenceParent.parentNode.code.startMode !== undefined) {
if (statusDependencyNode.referenceParent.parentNode.code.startMode.allMonths !== undefined) {
if (statusDependencyNode.referenceParent.parentNode.code.startMode.oneMonth !== undefined) {
if (statusDependencyNode.referenceParent.parentNode.code.startMode.allMonths.run === "true" || statusDependencyNode.referenceParent.parentNode.code.startMode.oneMonth.run === "true") {
statusDependencyNode.processRunMonthly = true
}
}
}
}
/* We retrieve the report main utility */
if (statusDependencyNode.code !== undefined) {
if (statusDependencyNode.code.mainUtility !== undefined) {
@@ -122,7 +113,74 @@
sessionPath = bot.SESSION.folderName + "/"
}
callBackFunction(global.DEFAULT_OK_RESPONSE);
/* Now we will see where do we need to fetch this status report from. */
let network = global.TASK_NETWORK
let processThisDependsOn = statusDependencyNode.referenceParent.parentNode
for (let i = 0; i < network.networkNodes.length; i++) {
let networkNode = network.networkNodes[i]
if (checkThisBranch(networkNode.dataMining) === true) { return }
if (checkThisBranch(networkNode.testingEnvironment) === true) {return}
if (checkThisBranch(networkNode.productionEnvironment) === true) { return }
function checkThisBranch(branch) {
if (branch === undefined) {return}
for (let j = 0; j < branch.exchangeTasks.length; j++) {
let exchangeTasks = branch.exchangeTasks[j]
for (let k = 0; k < exchangeTasks.taskManagers.length; k++) {
let taskManager = exchangeTasks.taskManagers[k]
for (let m = 0; m < taskManager.tasks.length; m++) {
let task = taskManager.tasks[m]
if (task.bot !== undefined) {
for (let n = 0; n < task.bot.processes.length; n++) {
let process = task.bot.processes[n]
if (process.marketReference !== undefined) {
if (process.marketReference.referenceParent !== undefined) {
let market = process.marketReference.referenceParent
let currentProcessMarket = bot.processNode.marketReference.referenceParent
if (currentProcessMarket.id === market.id) {
if (process.referenceParent !== undefined) {
let processDefinition = process.referenceParent
if (processThisDependsOn.id === processDefinition.id) {
if (process.type === 'Trading Process Instance') {
if (process.session !== undefined) {
if (bot.processNode.session.id !== process.session.id) {
continue
}
} else {
continue
}
}
/* We found where the task that runs the process definition this status report depends on and where it is located on the network. */
thisObject.networkNode = networkNode
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Retrieving status report from " + networkNode.name + " -> host = " + networkNode.code.host + ' -> port = ' + networkNode.code.webPort + '.'); }
fileStorage = FILE_STORAGE.newFileStorage(logger, networkNode.code.host, networkNode.code.webPort);
callBackFunction(global.DEFAULT_OK_RESPONSE);
return true
}
}
}
}
}
}
}
}
}
}
}
}
logger.write(MODULE_NAME, "[ERROR] initialize -> Initialization Failed because we could not find where the data of this status report is located within the network. Check the logs for more info.");
logger.write(MODULE_NAME, "[ERROR] initialize -> bot = " + statusDependencyNode.bot);
logger.write(MODULE_NAME, "[ERROR] initialize -> process = " + statusDependencyNode.process);
logger.write(MODULE_NAME, "[ERROR] initialize -> bottype = " + statusDependencyNode.bottype);
logger.write(MODULE_NAME, "[ERROR] initialize -> dataMine = " + statusDependencyNode.dataMine);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> err = "+ err.stack);
@@ -130,6 +188,13 @@
}
}
function finalize() {
fileStorage = undefined
thisObject.networkNode = undefined
bot = undefined
thisObject = undefined
}
function load(callBackFunction) {
try {
@@ -212,6 +277,7 @@
*/
logger.write(MODULE_NAME, "[ERROR] load -> onFileReceived -> Error Parsing the Status report. -> Err = " + err.message);
logger.write(MODULE_NAME, "[WARN] load -> onFileReceived -> Error Parsing the Status report. -> text = " + text);
let customFail = {
result: global.CUSTOM_FAIL_RESPONSE.result,
+16 -2
View File
@@ -213,6 +213,8 @@
record.maximumBalanceB + "," +
record.baseAsset + "," +
record.quotedAsset + "," +
record.marketBaseAsset + "," +
record.marketQuotedAsset + "," +
record.positionPeriods + "," +
record.positionDays + "," +
record.distanceToLastTriggerOn + "," +
@@ -559,8 +561,14 @@
record.maximumBalanceB + "," +
record.baseAsset + "," +
record.quotedAsset + "," +
record.marketBaseAsset + "," +
record.marketQuotedAsset + "," +
record.positionPeriods + "," +
record.positionDays + "]";
record.positionDays + "," +
record.distanceToLastTriggerOn + "," +
record.distanceToLastTriggerOff + "," +
record.distanceToLastTakePosition + "," +
record.distanceToLastClosePosition + "]";
if (separator === "") { separator = ","; }
@@ -664,8 +672,14 @@
record.maximumBalanceB + "," +
record.baseAsset + "," +
record.quotedAsset + "," +
record.marketBaseAsset + "," +
record.marketQuotedAsset + "," +
record.positionPeriods + "," +
record.positionDays + "]";
record.positionDays + "," +
record.distanceToLastTriggerOn + "," +
record.distanceToLastTriggerOff + "," +
record.distanceToLastTakePosition + "," +
record.distanceToLastClosePosition + "]";
if (separator === "") { separator = ","; }
+16 -2
View File
@@ -124,8 +124,11 @@
}
/* 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();
@@ -288,6 +291,12 @@
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;
}
@@ -694,6 +703,10 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Entering function."); }
processFramework.finalize()
processFramework = undefined
dataDependencies.finalize()
dataDependencies = undefined
statusDependencies.finalize()
statusDependencies = undefined
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
@@ -792,8 +805,9 @@
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
processExecutionEvents.finalize()
processExecutionEvents = undefined
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); }
+2
View File
@@ -2798,6 +2798,8 @@
maximumBalanceB: bot.VALUES_TO_USE.maximumBalanceB,
baseAsset: quotedBaseAsset,
quotedAsset: quotedQuotedAsset,
marketBaseAsset: '"' + bot.market.baseAsset + '"',
marketQuotedAsset: '"' + bot.market.quotedAsset + '"' ,
positionPeriods: positionPeriods,
positionDays: positionDays,
distanceToLastTriggerOn: distanceToLast.triggerOn,
+35 -6
View File
@@ -26,19 +26,37 @@ global.CUSTOM_FAIL_RESPONSE = {
};
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
global.LOGGER_MAP = new Map()
global.SESSION_MAP = new Map()
process.on('uncaughtException', function (err) {
console.log('[ERROR] Task Server -> server -> uncaughtException -> err.message = ' + err.message)
console.log('[ERROR] Task Server -> server -> uncaughtException -> err.stack = ' + err.stack)
process.exit(1)
global.EXIT_NODE_PROCESS()
})
process.on('unhandledRejection', (reason, p) => {
console.log('[ERROR] Task Server -> server -> unhandledRejection -> reason = ' + JSON.stringify(reason))
console.log('[ERROR] Task Server -> server -> unhandledRejection -> p = ' + JSON.stringify(p))
process.exit(1)
global.EXIT_NODE_PROCESS()
})
function finalizeLoggers() {
global.LOGGER_MAP.forEach(forEachLogger)
function forEachLogger(logger) {
logger.finalize()
}
}
function finalizeSessions() {
global.SESSION_MAP.forEach(forEachSession)
function forEachSession(session) {
global.EVENT_SERVER_CLIENT.raiseEvent(session, 'Stopped')
}
}
process.on('exit', function (code) {
if (global.TASK_NODE !== undefined) {
@@ -69,8 +87,16 @@ process.on('message', message => {
}
});
let shuttingDownProcess = false
global.EXIT_NODE_PROCESS = function exitProcess() {
if (shuttingDownProcess === true) { return }
shuttingDownProcess = true
/* Signal that all sessions are stopping. */
finalizeSessions()
/* Cleaning Before Exiting. */
clearInterval(global.HEARTBEAT_INTERVAL_HANDLER)
@@ -82,6 +108,7 @@ global.EXIT_NODE_PROCESS = function exitProcess() {
global.EVENT_SERVER_CLIENT.raiseEvent(key, 'Stopped') // Meaning Process Stopped
}
finalizeLoggers()
//console.log("[INFO] Task Server -> " + global.TASK_NODE.name + " -> EXIT_NODE_PROCESS -> Task Server will stop in 10 seconds.");
setTimeout(process.exit, 10000) // We will give 10 seconds to logs be written on file
@@ -125,12 +152,13 @@ function preLoader() {
global.EVENT_SERVER_CLIENT.raiseEvent('Task Manager - ' + taskId, 'Nodejs Process Ready for Task')
function eventReceived(message) {
global.TASK_NODE = message
global.TASK_NODE = JSON.parse(message.event.definition)
global.TASK_NODE = JSON.parse(message.event.taskDefinition)
global.TASK_NETWORK = JSON.parse(message.event.networkDefinition)
bootLoader()
}
} catch (err) {
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE -> ' + err.stack)
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE))
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE).substring(0, 1000))
}
}
else { /* This process was started not by the Task Manager, but independently (most likely for debugging purposes). In this case we listen to an event with the Task Info that should be emitted at the UI */
@@ -139,12 +167,13 @@ function preLoader() {
global.EVENT_SERVER_CLIENT.listenToEvent('Task Server', 'Debug Task Started', undefined, 'Task Server', undefined, startDebugging)
function startDebugging(message) {
global.TASK_NODE = message
global.TASK_NODE = JSON.parse(message.event.definition)
global.TASK_NODE = JSON.parse(message.event.taskDefinition)
global.TASK_NETWORK = JSON.parse(message.event.networkDefinition)
bootLoader()
}
} catch (err) {
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE -> ' + err.stack)
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE))
console.log('[ERROR] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE).substring(0, 1000))
}
}
}
+1 -1
View File
@@ -1 +1 @@
{"type":"Trading System","name":"Bull Run Rider for BTC/USDT","code":"{ \n\"codeName\": \"Sparta-BRR-BTC-USDT\"\n}","strategies":[{"type":"Strategy","name":"My Strategy","triggerStage":{"type":"Trigger Stage","triggerOn":{"type":"Trigger On Event","situations":[{"type":"Situation","name":"New Situation","conditions":[{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.max > chart.at01hs.bollingerBand.movingAverage + chart.at01hs.bollingerBand.deviation","id":"1e07e38a-c469-4f3f-b7e8-dccd9f94c546","savedPayload":{"position":{"x":39365.82836640363,"y":18024.168218963674},"targetPosition":{"x":39580.43309418583,"y":18013.241510980984},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a1c434c4-5787-4906-8157-1e355999bba8","savedPayload":{"position":{"x":39580.43309418583,"y":18013.241510980984},"targetPosition":{"x":39795.82183026887,"y":18002.339607729755},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.previous.max > chart.at01hs.bollingerBand.previous.movingAverage + chart.at01hs.bollingerBand.previous.deviation\n","id":"3fb95a71-efe8-45cf-be43-8b0d94d2f420","savedPayload":{"position":{"x":39560.74976017509,"y":17641.37546255235},"targetPosition":{"x":39677.97500609048,"y":17821.555824077757},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"f69f2608-49bd-4b04-b8f8-497675f819fe","savedPayload":{"position":{"x":39677.97500609048,"y":17821.555824077757},"targetPosition":{"x":39795.82183026887,"y":18002.339607729755},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1dfb0689-df0c-4184-9c09-683d012c9dfe","savedPayload":{"position":{"x":39795.82183026887,"y":18002.339607729755},"targetPosition":{"x":39987.61800165299,"y":18099.825253218787},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"announcements":[],"id":"32d2ee8c-71bd-4e4c-8671-04bbc4a16734","savedPayload":{"position":{"x":39987.61800165299,"y":18099.825253218787},"targetPosition":{"x":40369.80868599963,"y":18293.946872397046},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"triggerOff":{"type":"Trigger Off Event","situations":[{"type":"Situation","name":"New Situation","conditions":[{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.close < chart.at01hs.bollingerBand.movingAverage","id":"a1dd4467-b96b-4084-bd9b-056c6495de95","savedPayload":{"position":{"x":40036.90604970189,"y":17272.087105877887},"targetPosition":{"x":40103.63478212326,"y":17476.753747464914},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b527026c-4be3-4baf-bbde-83ebfd17e567","savedPayload":{"position":{"x":40103.63478212326,"y":17476.753747464914},"targetPosition":{"x":40170.46021986034,"y":17681.58479868604},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"41cbb7ba-020c-4e96-a6a7-c3ef8c25b6fd","savedPayload":{"position":{"x":40170.46021986034,"y":17681.58479868604},"targetPosition":{"x":40237.14613497818,"y":17886.475906641663},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"announcements":[],"id":"1af9fdb8-7316-4374-84f2-1b946741b5c6","savedPayload":{"position":{"x":40237.14613497818,"y":17886.475906641663},"targetPosition":{"x":40369.80868599963,"y":18293.946872397046},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"takePosition":{"type":"Take Position Event","situations":[{"type":"Situation","name":"New Situation","conditions":[{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.previous.max > chart.at01hs.bollingerBand.previous.movingAverage + chart.at01hs.bollingerBand.previous.deviation\n","id":"0c15bd8b-b59c-4a2c-b65a-b063aec45216","savedPayload":{"position":{"x":40373.57878568003,"y":17396.87030065395},"targetPosition":{"x":40513.12406224243,"yLine truncated
{"type":"Trading System","name":"Bull Run Rider for BTC/USDT","code":"{ \n\"codeName\": \"Sparta-BRR-BTC-USDT\"\n}","strategies":[{"type":"Strategy","name":"My Strategy","triggerStage":{"type":"Trigger Stage","triggerOn":{"type":"Trigger On Event","situations":[{"type":"Situation","name":"New Situation","conditions":[{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.max > chart.at01hs.bollingerBand.movingAverage + chart.at01hs.bollingerBand.deviation","id":"1e07e38a-c469-4f3f-b7e8-dccd9f94c546","savedPayload":{"position":{"x":32136.28636024774,"y":18006.129040560536},"targetPosition":{"x":32356.411078541598,"y":17994.8611316122},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"a1c434c4-5787-4906-8157-1e355999bba8","savedPayload":{"position":{"x":32356.411078541598,"y":17994.8611316122},"targetPosition":{"x":32576.81076551354,"y":17983.560786264006},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.previous.max > chart.at01hs.bollingerBand.previous.movingAverage + chart.at01hs.bollingerBand.previous.deviation\n","id":"3fb95a71-efe8-45cf-be43-8b0d94d2f420","savedPayload":{"position":{"x":32336.278054047183,"y":17613.80662251148},"targetPosition":{"x":32456.46036116711,"y":17798.592583814658},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"f69f2608-49bd-4b04-b8f8-497675f819fe","savedPayload":{"position":{"x":32456.46036116711,"y":17798.592583814658},"targetPosition":{"x":32576.81076551354,"y":17983.560786264006},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"1dfb0689-df0c-4184-9c09-683d012c9dfe","savedPayload":{"position":{"x":32576.81076551354,"y":17983.560786264006},"targetPosition":{"x":32773.13118473049,"y":18083.48293309789},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"announcements":[],"id":"32d2ee8c-71bd-4e4c-8671-04bbc4a16734","savedPayload":{"position":{"x":32773.13118473049,"y":18083.48293309789},"targetPosition":{"x":33165.111331477776,"y":18282.94927462636},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"triggerOff":{"type":"Trigger Off Event","situations":[{"type":"Situation","name":"New Situation","conditions":[{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.close < chart.at01hs.bollingerBand.movingAverage","id":"a1dd4467-b96b-4084-bd9b-056c6495de95","savedPayload":{"position":{"x":32824.239213958535,"y":17235.66806596493},"targetPosition":{"x":32892.45262811099,"y":17445.325022978603},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"b527026c-4be3-4baf-bbde-83ebfd17e567","savedPayload":{"position":{"x":32892.45262811099,"y":17445.325022978603},"targetPosition":{"x":32960.82113677954,"y":17655.21646975055},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"41cbb7ba-020c-4e96-a6a7-c3ef8c25b6fd","savedPayload":{"position":{"x":32960.82113677954,"y":17655.21646975055},"targetPosition":{"x":33029.05799170436,"y":17864.75284364219},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"announcements":[],"id":"1af9fdb8-7316-4374-84f2-1b946741b5c6","savedPayload":{"position":{"x":33029.05799170436,"y":17864.75284364219},"targetPosition":{"x":33165.111331477776,"y":18282.94927462636},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"takePosition":{"type":"Take Position Event","situations":[{"type":"Situation","name":"New Situation","conditions":[{"type":"Condition","name":"New Condition","javascriptCode":{"type":"Javascript Code","code":"chart.at01hs.candle.previous.max > chart.at01hs.bollingerBand.previous.movingAverage + chart.at01hs.bollingerBand.previous.deviation\n","id":"0c15bd8b-b59c-4a2c-b65a-b063aec45216","savedPayload":{"position":{"x":33171.57121687983,"y":17363.232196850764},"targetPosition":{"x":33314.699085071785,"y":1Line truncated
+1 -1
View File
@@ -1 +1 @@
{"type":"Workspace","name":"My Workspace","rootNodes":[{"type":"Network","name":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","code":"{ \n\"ipAddress\": \"\", \n\"webPort\": \"\", \n\"webSocketsPort\": \"\"\n}","dataStorage":{"type":"Data Storage","name":"New Data Storage","sessionIndependentData":{"type":"Session Independent Data","name":"New Session Independent Data","exchangeDataProducts":[{"type":"Exchange Data Products","name":"Binance","singleMarketData":[{"type":"Single Market Data","name":"Binance BTC/USDT","dataProducts":[{"type":"Data Product","name":"Candles","id":"24c141e4-1ed2-48ac-a034-7356312e82f9","savedPayload":{"position":{"x":39933.49393163037,"y":29046.10981068428},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"130cba4c-0c21-4955-88b9-e66d2b9abed0","savedPayload":{"position":{"x":39908.11948414529,"y":28963.262354549173},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"e0e5315b-d9a1-4763-80ac-649932acb5b0","savedPayload":{"position":{"x":39895.18349066973,"y":28880.38336833146},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"f9d97733-0919-4cbe-9e9e-b622ff629bc1","savedPayload":{"position":{"x":39893.27964669049,"y":28797.90081457585},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"97e49713-d0ba-4678-8703-aafc343c7972","savedPayload":{"position":{"x":39901.90265885927,"y":28716.54731001258},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"8169b2ef-9761-4bf7-9059-258f579a35c5","savedPayload":{"position":{"x":39920.664403351046,"y":28637.27326471363},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"2629ed65-1f0b-4a39-89b6-5f4492439363","savedPayload":{"position":{"x":39949.20152839712,"y":28561.15482568263},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"a536f2a1-6474-490b-a62b-724cc404acbd","savedPayload":{"position":{"x":39987.032994167246,"y":28489.298406726437},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"36245c8b-614d-4bea-8e92-fe45babcb936","savedPayload":{"position":{"x":40033.55648252736,"y":28422.790182572182},"targetPosition":{"x":40538.49727374207,"y":28825.59791579029},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"anLine truncated
{"type":"Workspace","name":"My Workspace","rootNodes":[{"type":"Network","name":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","code":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34247\", \n\"webSocketsPort\": \"8080\"\n}","dataStorage":{"type":"Data Storage","name":"New Data Storage","sessionIndependentData":{"type":"Session Independent Data","name":"New Session Independent Data","exchangeDataProducts":[{"type":"Exchange Data Products","name":"Binance","singleMarketData":[{"type":"Single Market Data","name":"Binance BTC/USDT","dataProducts":[{"type":"Data Product","name":"Candles","id":"431ea989-085b-40ae-aa2a-d371d7cb68c6","savedPayload":{"position":{"x":39641.333811210454,"y":28936.98413868935},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"cc76acbb-9fd2-43f0-95de-dc78e1aaa2b5","savedPayload":{"position":{"x":39612.59634583407,"y":28848.5110343909},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"683e24f7-010a-412e-ba21-f280e63a0f1d","savedPayload":{"position":{"x":39594.15352768551,"y":28758.904338266497},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"210b7e14-a6f0-4c56-b5e4-108f57ebb4c6","savedPayload":{"position":{"x":39585.513470979095,"y":28668.600155855387},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"ddd34b26-4fa8-4d7c-b76d-f671c92a6181","savedPayload":{"position":{"x":39586.515890435076,"y":28578.275802249987},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"302bfaf2-6466-4aa0-9924-33999366b774","savedPayload":{"position":{"x":39597.01323868843,"y":28488.759535006342},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"10142313-9ac8-4f4c-8105-88aec7bb7ce9","savedPayload":{"position":{"x":39616.82107043368,"y":28400.936525998834},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"80ed873e-8017-45ec-b211-fc4604f5aaf6","savedPayload":{"position":{"x":39645.70528040039,"y":28315.720626172813},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"6635502b-5366-430e-8dc1-4edaa21c2a7f","savedPayload":{"position":{"x":39683.34058679891,"y":28234.020419812852},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":fLine truncated