Merge branch 'Superalgos:develop' into develop

This commit is contained in:
B Harrell committed 2021-05-28 12:44:13 -05:00
commit 12ea0c809b
34 files changed
+432 -286

No files matched your search

+1 -1
View File
@@ -1112,7 +1112,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
let fs = require('fs')
try {
let filePath = global.env.PATH_TO_DEFAULT_WORKSPACE + '/Getting-Started.json'
let filePath = global.env.PATH_TO_DEFAULT_WORKSPACE + '/Getting-Started-Tutorials.json'
fs.readFile(filePath, onFileRead)
} catch (e) {
console.log('[ERROR] Error reading the Workspace.', e)
@@ -0,0 +1 @@
{"type":"Workspace","name":"Getting Started Tutorials","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataTasks":{"type":"Data Tasks","name":"New Data Tasks","project":"Superalgos","projectDataTasks":[{"type":"Project Data Tasks","name":"Superalgos","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Resistances and Supports","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Resistances and Supports","config":"{ \n\"parameter1\": \"Value for parameter1 defined at the Product Definition\"\n}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Time-Frame-Market","project":"Superalgos","id":"afeed756-c931-4f34-b27c-12fd2b5ef39a","savedPayload":{"position":{"x":23310.348760844034,"y":29310.042580543206},"targetPosition":{"x":23600.126508730755,"y":29387.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Time-Frame-Market","id":"5d9b2729-43fb-4e7e-aa4f-b8477c424e51"}}},{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Time-Frame-Daily","project":"Superalgos","id":"f11443df-d85b-486c-acaf-a446a5086c09","savedPayload":{"position":{"x":23387.99447437479,"y":29175.556259718},"targetPosition":{"x":23600.126508730755,"y":29387.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Time-Frame-Daily","id":"be19d91b-9337-4f84-96b3-f4e54ea12df5"}}}],"id":"e644a294-b0f0-4996-817e-0d95f92042d5","savedPayload":{"position":{"x":23600.126508730755,"y":29387.688294073963},"targetPosition":{"x":23859.934129866087,"y":29537.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0f9200a1-81fe-4ef4-affc-f4a00c89a52a","savedPayload":{"position":{"x":23859.934129866087,"y":29537.688294073963},"targetPosition":{"x":24119.74175100142,"y":29687.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"6e864d3c-4660-42c2-8499-7db31789fd12","savedPayload":{"position":{"x":24119.74175100142,"y":29687.688294073963},"targetPosition":{"x":24379.549372136753,"y":29837.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e04f5978-a32c-4950-a7e3-d2b8c0658000","savedPayload":{"position":{"x":24379.549372136753,"y":29837.688294073963},"targetPosition":{"x":24639.356993272086,"y":29987.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Masters","id":"35be7b1c-a0f7-4b5f-9ee1-8fb51595e959"}}},{"type":"Data Mine Tasks","name":"Candles","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Candles","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{\n \"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"ef7ba335-da83-4c53-9bb2-480360223fb5","savedPayload":{"position":{"x":24189.356993272086,"y":28608.265430667965},"targetPosition":{"x":24339.356993272086,"y":28868.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"92b80bac-30e0-410a-ac74-c8894ed52b64","savedPayload":{"position":{"x":24339.356993272086,"y":28868.073051803298},"targetPosition":{"x":24489.356993272086,"y":29127.88067293863},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToPLine truncated
@@ -1 +0,0 @@
{"type":"Workspace","name":"Getting Started","rootNodes":[{"type":"Network","name":"My Network","project":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","config":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34248\", \n\"webSocketsPort\": \"18041\"\n}","project":"Superalgos","dataTasks":{"type":"Data Tasks","name":"New Data Tasks","project":"Superalgos","projectDataTasks":[{"type":"Project Data Tasks","name":"Superalgos","project":"Superalgos","exchangeDataTasks":[{"type":"Exchange Data Tasks","name":"Binance","project":"Superalgos","marketDataTasks":[{"type":"Market Data Tasks","name":"Binance BTC/USDT","project":"Superalgos","dataMineTasks":[{"type":"Data Mine Tasks","name":"Masters","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Masters","project":"Superalgos","tasks":[{"type":"Task","name":"Resistances and Supports","project":"Superalgos","bot":{"type":"Indicator Bot Instance","name":"Resistances and Supports","config":"{ \n\"parameter1\": \"Value for parameter1 defined at the Product Definition\"\n}","project":"Superalgos","processes":[{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Time-Frame-Market","project":"Superalgos","id":"afeed756-c931-4f34-b27c-12fd2b5ef39a","savedPayload":{"position":{"x":23310.348760844034,"y":29310.042580543206},"targetPosition":{"x":23600.126508730755,"y":29387.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Time-Frame-Market","id":"5d9b2729-43fb-4e7e-aa4f-b8477c424e51"}}},{"type":"Indicator Process Instance","name":"Resistances and Supports Multi-Time-Frame-Daily","project":"Superalgos","id":"f11443df-d85b-486c-acaf-a446a5086c09","savedPayload":{"position":{"x":23387.99447437479,"y":29175.556259718},"targetPosition":{"x":23600.126508730755,"y":29387.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Multi-Time-Frame-Daily","id":"be19d91b-9337-4f84-96b3-f4e54ea12df5"}}}],"id":"e644a294-b0f0-4996-817e-0d95f92042d5","savedPayload":{"position":{"x":23600.126508730755,"y":29387.688294073963},"targetPosition":{"x":23859.934129866087,"y":29537.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"id":"0f9200a1-81fe-4ef4-affc-f4a00c89a52a","savedPayload":{"position":{"x":23859.934129866087,"y":29537.688294073963},"targetPosition":{"x":24119.74175100142,"y":29687.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"6e864d3c-4660-42c2-8499-7db31789fd12","savedPayload":{"position":{"x":24119.74175100142,"y":29687.688294073963},"targetPosition":{"x":24379.549372136753,"y":29837.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}}],"id":"e04f5978-a32c-4950-a7e3-d2b8c0658000","savedPayload":{"position":{"x":24379.549372136753,"y":29837.688294073963},"targetPosition":{"x":24639.356993272086,"y":29987.688294073963},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Data Mine","name":"Masters","id":"35be7b1c-a0f7-4b5f-9ee1-8fb51595e959"}}},{"type":"Data Mine Tasks","name":"Candles","project":"Superalgos","taskManagers":[{"type":"Task Manager","name":"Candles","project":"Superalgos","tasks":[{"type":"Task","name":"Exchange Raw Data","project":"Superalgos","bot":{"type":"Sensor Bot Instance","name":"Exchange Raw Data","config":"{\n \"startDate\": \"2020-01-01\"\n}","project":"Superalgos","processes":[{"type":"Sensor Process Instance","name":"Exchange Raw Data Historic-OHLCVs","project":"Superalgos","id":"ef7ba335-da83-4c53-9bb2-480360223fb5","savedPayload":{"position":{"x":24189.356993272086,"y":28608.265430667965},"targetPosition":{"x":24339.356993272086,"y":28868.073051803298},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":3,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Process Definition","name":"Historic-OHLCVs","id":"5eb11d6a-022e-4f60-97c4-d6cf90b249dc"}}}],"id":"92b80bac-30e0-410a-ac74-c8894ed52b64","savedPayload":{"position":{"x":24339.356993272086,"y":28868.073051803298},"targetPosition":{"x":24489.356993272086,"y":29127.88067293863},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"Line truncated
@@ -1,8 +1,8 @@
{
"type": "Plugin Workspace",
"definition": {
"text": "This refers to a Workspace created by a user, contributed to the project as a plugin and distributed with the whole software package. Plugin workspaces are useful to give access to users to ready to run strategies, demos, tutorials or areas of the system under development.",
"updated": 1622053231319
"text": "Refers to a Workspace created by a user, contributed to the project as a plugin and distributed with the whole software package. Plugin workspaces are useful to give access to users to ready-to-run strategies, demos, tutorials, or areas of the system under development.",
"updated": 1622193639612
},
"paragraphs": [
{
@@ -1,8 +1,8 @@
{
"type": "UI",
"definition": {
"text": "UI is an abbreviation for User Interface (user interface), which refers to the operation screen and operation method of the software. In Superalgos the UI is a Web App that runs at an Internet Browser.",
"updated": 1610911735769
"text": "UI is an abbreviation for User Interface, which refers to the operation screen and operation method of the software. In Superalgos the UI is a Web App that runs on an Internet Browser.",
"updated": 1622192912866
},
"paragraphs": [
{
@@ -1,8 +1,8 @@
{
"type": "User Workspace",
"definition": {
"text": "This refers to a Workspace created by a user, and stored locally at the My Workspaces folder.",
"updated": 1622053351023
"text": "Refers to a Workspace created by a user, and stored locally at the My-Workspaces folder.",
"updated": 1622192760962
},
"paragraphs": [
{
@@ -7,7 +7,7 @@
"project": "Superalgos",
"name": "binance"
},
"text": "Before we start data mining, I have a little question for you: are you trading at binance.com or binance.us?",
"text": "Before we start data mining, I have a little question for you: are you trading at binance.com, binance.us, or neither?",
"translations": [
{
"language": "IT",
@@ -27,7 +27,8 @@
"updated": 1618434029175,
"style": "Definition"
}
]
],
"updated": 1622189667210
},
"paragraphs": [
{
@@ -81,8 +82,8 @@
},
{
"style": "List",
"text": "Open the configuration and change the codeName to binanceus. Move the mouse pointer out of the configuration bubble and it will close and save automatically.",
"updated": 1616414675945,
"text": "Access the configuration and change the codeName to \"binanceus\". Move the mouse pointer out of the configuration bubble and it will close and save automatically.",
"updated": 1622189775201,
"translations": [
{
"language": "IT",
@@ -106,8 +107,8 @@
},
{
"style": "List",
"text": "Edit the label of the node to read Binanceus.",
"updated": 1616414681256,
"text": "Edit the label of the node to read \"Binanceus\".",
"updated": 1622189798374,
"translations": [
{
"language": "IT",
@@ -7,8 +7,8 @@
"project": "Superalgos",
"name": "run"
},
"text": "Open the Data Tasks node menu and find the Run All Project Data Tasks button on the top-right corner...",
"updated": 1611076262685,
"text": "Access the Data Tasks node menu and find the \"Run all project data tasks\" button on the top-right corner...",
"updated": 1622189956451,
"translations": [
{
"language": "IT",
@@ -25,15 +25,16 @@
{
"language": "ES",
"text": "Abra el menú del nodo Data Tasks y busque el botón Run All Project Data Tasks en la esquina superior derecha...",
"updated": 1618434308521
"updated": 1618434308521,
"style": "Definition"
}
]
},
"paragraphs": [
{
"style": "Callout",
"text": "Click the Run All Project Data Tasks button!",
"updated": 1611076332667,
"text": "Click the \"Run all project data tasks\" button! Confirm the request by clicking the button a second time.",
"updated": 1622190007548,
"translations": [
{
"language": "IT",
@@ -50,13 +51,14 @@
{
"language": "ES",
"text": "Haz click en el botón Run All Project Data Tasks!",
"updated": 1618434334439
"updated": 1618434334439,
"style": "Callout"
}
]
},
{
"style": "Text",
"text": "Confirm the request by clicking the button a second time. In about 30 seconds, you should see a status notice below the Data Mining node indicating that 1 out of 1 Exchange Data Tasks node is running.",
"text": "In about 30 seconds, you should see a status notice below the Data Tasks node indicating that 1 out of 1 Exchange Data Tasks node is running.",
"translations": [
{
"language": "IT",
@@ -73,9 +75,11 @@
{
"language": "ES",
"text": "Confirme la solicitud haciendo clic en el botón por segunda vez. En unos 30 segundos, debería ver un aviso de estado bajo el nodo Data Mining que indica que se está ejecutando 1 out of 1 Exchange Data Tasks.",
"updated": 1618434426749
"updated": 1618434426749,
"style": "Text"
}
]
],
"updated": 1622190035816
},
{
"style": "Note",
@@ -96,7 +100,8 @@
{
"language": "ES",
"text": "Tu aplicación de consola, deberia mostrar algo similar a lo que aparece en el video, a continuación",
"updated": 1618434455552
"updated": 1618434455552,
"style": "Note"
}
]
}
@@ -24,7 +24,8 @@
{
"language": "ES",
"text": "En este punto, probablemente esté saturando tu hipocampo! Pero no te preocupes... ¡puedes volver a cualquier paso anterior!",
"updated": 1618436677513
"updated": 1618436677513,
"style": "Definition"
}
]
},
@@ -48,7 +49,8 @@
{
"language": "ES",
"text": "Si alguna vez necesitas un recordatorio sobre estos temas...",
"updated": 1618436771239
"updated": 1618436771239,
"style": "Text"
}
]
},
@@ -71,14 +73,15 @@
{
"language": "ES",
"text": "Busque el Tutorial Topic y reprodúzcalo! Puede encontrarme en la esquina inferior izquierda del Desing Space, expandirme, navegar por la jerarquía de temas y pasos, y hacer clic en Play en cualquiera de ellos. Los temas están ordenados en el sentido de las agujas del reloj, empezando por la derecha del nodo principal de Tutorial.",
"updated": 1618436934915
"updated": 1618436934915,
"style": "List"
}
]
},
{
"style": "Callout",
"text": "Need a Quick Reminder? Find the step under the Tutorials & Help topic below. Then click Stop, and restart by clicking Play on the said Tutorial Step!",
"updated": 1611076850328,
"text": "\"Need a Quick Reminder?\" Find this step under the \"Tutorials & Help\" topic below. Then click Stop, and restart by clicking Play on the said Tutorial Step!",
"updated": 1622192045886,
"translations": [
{
"language": "IT",
@@ -95,7 +98,8 @@
{
"language": "ES",
"text": "Necesitas refrescar tu memoria? Busque el paso en el tema de Tutorials & Help. A continuación, haga clic en Stop y reinicie haciendo clic en Play en dicho paso del tutorial.",
"updated": 1618437112467
"updated": 1618437112467,
"style": "Callout"
}
]
}
@@ -24,14 +24,15 @@
{
"language": "ES",
"text": "Si alguna vez rompes algo -como borrar un nodo por error o cambiar la configuración- y no sabes cómo afrontar el resultado...",
"updated": 1618438157553
"updated": 1618438157553,
"style": "Definition"
}
]
},
"paragraphs": [
{
"style": "Callout",
"text": "... there is an easy way to start over with a brand new workspace!",
"text": "... you may easily start over with the original Getting Started Tutorials Plugin Workspace!",
"translations": [
{
"language": "IT",
@@ -48,13 +49,15 @@
{
"language": "ES",
"text": "Hay una manera facil de empezar con un espacio de trabajo como nuevo",
"updated": 1618438101054
"updated": 1618438101054,
"style": "Callout"
}
]
],
"updated": 1622196973760
},
{
"style": "Text",
"text": "All you need to do is pull the tab on the left-hand side of the screen and click on the Getting-Started plugin workspace.",
"text": "All you need to do is pull the tab on the left-hand side of the screen, scroll and find the Getting Started Tutorials plugin workspace and click it!",
"translations": [
{
"language": "IT",
@@ -71,13 +74,15 @@
{
"language": "ES",
"text": "Todo lo que tienes que hacer es tirar de la pestaña de la izquierda de la pantalla y hacer clic en Getting-Started plugin workspace.",
"updated": 1618438234984
"updated": 1618438234984,
"style": "Text"
}
]
],
"updated": 1622193846331
},
{
"style": "Success",
"text": "A brand new Getting Started workspace will load and I will show up again, fresh from the start!",
"text": "The original Plugin Workspace will load and the tutorial will show up again, fresh from the start!",
"translations": [
{
"language": "IT",
@@ -94,9 +99,11 @@
{
"language": "ES",
"text": "Se cargará un nuevo espacio de trabajo de \"Getting Started\" y apareceré de nuevo, fresco desde el principio!",
"updated": 1618438286128
"updated": 1618438286128,
"style": "Success"
}
]
],
"updated": 1622193879709
}
]
}
@@ -7,7 +7,7 @@
"project": "Superalgos",
"name": "workspace"
},
"text": "Yes! Some of them are plugins shipping with the system and some are your own!",
"text": "Most are Plugin Workspaces shipping with the system! There should be one User Workspace at the end of the list too!",
"translations": [
{
"language": "IT",
@@ -24,15 +24,17 @@
{
"language": "ES",
"text": "Sí. Algunos de ellos son plugins que vienen con el sistema y otros son los tuyos propios! ",
"updated": 1618438936999
"updated": 1618438936999,
"style": "Definition"
}
]
],
"updated": 1622193005692
},
"paragraphs": [
{
"style": "Text",
"text": "As soon as you start using the system, the workspace is saved every minute. It is also saved before closing the browser or browser tab, and you may save it manually using the Ctrl + Shift + Key-S",
"updated": 1610614718976,
"text": "As soon as you launched the UI for the first time, the Getting Started Tutorials Plugin Workspace was loaded. The Workspace was saved as a new User Workspace after 60 seconds in the My-Workspaces folder.",
"updated": 1622193268470,
"translations": [
{
"language": "IT",
@@ -49,36 +51,19 @@
{
"language": "ES",
"text": "Tan pronto como empiezas a usar el sistema, el workspace es guardado cada minuto. También se guarda antes de cerrar el navegador o la pestaña del navegador, y puedes guardarlo manualmente utilizando las teclas Ctrl + Shift + Key-S",
"updated": 1618439054191
"updated": 1618439054191,
"style": "Text"
}
]
},
{
"style": "Callout",
"text": "When a plugin workspace is modified in any way, a copy is stored in your My-Workspaces folder.",
"translations": [
{
"language": "IT",
"text": "Quando un plugin workspace viene modificato in qualunque modo, una copia viene salvata su disco nella tua cartella My-Workspaces.",
"updated": 1614791526653,
"style": "Callout"
},
{
"language": "ID",
"text": "Saat workspace plugin dimodifikasi dalam cara apapun, salinan akan tersimpan di folder My-Workspaces.",
"updated": 1616770626561,
"style": "Callout"
},
{
"language": "ES",
"text": "Cuando un plugin workspace se modifica de alguna manera, se almacena una copia en la carpeta My-Workspaces.",
"updated": 1618439039856
}
]
"style": "Success",
"text": "The Workspace is saved automatically every minute. It is also saved before closing the browser or browser tab, and you may save it manually using the Ctrl + Shift + Key-S",
"updated": 1622193961757
},
{
"style": "Important",
"text": "Plugin files may not be modified from within the system!",
"text": "Changes is Plugins Workspaces don't persist in the plugin. They do in the User Workspace",
"translations": [
{
"language": "IT",
@@ -95,9 +80,11 @@
{
"language": "ES",
"text": "Los archivos de los plugins no pueden ser modificados desde el sistema!",
"updated": 1618439194749
"updated": 1618439194749,
"style": "Important"
}
]
],
"updated": 1622193520113
}
]
}
@@ -7,7 +7,7 @@
"project": "Superalgos",
"name": "data-tasks"
},
"text": "Now that you're comfortable moving around, I want you to go on a little tour exploring the Data Tasks section of the hierarchy.",
"text": "Now that you're comfortable moving around, I want you to go on a little tour exploring the Data Tasks section of the Network Node.",
"translations": [
{
"language": "IT",
@@ -24,9 +24,11 @@
{
"language": "ES",
"text": "Ahora que te sientes cómodo por aqui, quiero que hagas un pequeño recorrido explorando la sección Data Tasks de la jerarquía.",
"updated": 1618439383864
"updated": 1618439383864,
"style": "Definition"
}
]
],
"updated": 1622194034630
},
"paragraphs": [
{
@@ -48,7 +50,8 @@
{
"language": "ES",
"text": "Fijate en lo siguiente",
"updated": 1618439399867
"updated": 1618439399867,
"style": "Text"
}
]
},
@@ -71,7 +74,8 @@
{
"language": "ES",
"text": "La sección está organizada, en primer lugar, por proyecto, exchage y mercado. Esto le ayudará a trabajar con varios exchanges y mercados de forma ordenada.",
"updated": 1618439477366
"updated": 1618439477366,
"style": "List"
}
]
},
@@ -94,7 +98,8 @@
{
"language": "ES",
"text": "Los nodos de Exchange Data Tasks y Market Data Tasks pueden controlar todas las tareas del exchange y del mercado respectivamente.",
"updated": 1618439583481
"updated": 1618439583481,
"style": "List"
}
]
},
@@ -117,7 +122,8 @@
{
"language": "ES",
"text": "Salga y explore esos nodos y sus menús.",
"updated": 1618439650404
"updated": 1618439650404,
"style": "Callout"
}
]
}
@@ -18,7 +18,8 @@
{
"language": "ID",
"text": "Disetiap market, operasi diorganisasi melalui Data Mine. Superlagos berkerjasama dengan beberapa data mine open-source, dan setiap darinya memiliki banyak indicator.",
"updated": 1616771187052
"updated": 1616771187052,
"style": "Definition"
}
]
},
@@ -36,13 +37,14 @@
{
"language": "ID",
"text": "Pikirkan data mine sebagai plugin yang developer akan buat untuk memperpanjang kapasitas analisis data dari sistem. Indicator Bot akan memproses data, indikator lain akan membuatnya, sehingga menambah nilai dan menghasilkan analisis yang lebih dalam dan lebih kaya.",
"updated": 1616771335447
"updated": 1616771335447,
"style": "Text"
}
]
},
{
"style": "Callout",
"text": "If you have a basic understanding of JavaScript, you may create indicators too!",
"text": "If you have a basic understanding of JavaScript, you may create indicators too! If you contribute a Data Mine, you earn Superalgos (SA) Tokens!",
"translations": [
{
"language": "IT",
@@ -53,9 +55,11 @@
{
"language": "ID",
"text": "Jika kamu memiliki pemahaman dasar tentang JavaScript, kamu juga dapat membuat indikator!",
"updated": 1616771371122
"updated": 1616771371122,
"style": "Callout"
}
]
],
"updated": 1622196189467
},
{
"style": "Text",
@@ -70,7 +74,8 @@
{
"language": "ID",
"text": "Tapi aku terlalu terburu-buru berbicara tentang membangun data mine pada saat ini! Ayo kembali ke jalurnya!",
"updated": 1616771422206
"updated": 1616771422206,
"style": "Text"
}
]
}
@@ -83,7 +83,7 @@
},
{
"style": "Callout",
"text": "If all processes are up to date, then select Stop All Tasks in the Masters Task Manager. If not, wait a bit longer!",
"text": "When all processes are up to date, select \"Stop All Tasks\" in the Market Data Tasks node. Notice that we can stop the tasks from a different node than the one we used to start them!",
"translations": [
{
"language": "IT",
@@ -98,7 +98,7 @@
"style": "Callout"
}
],
"updated": 1616415772977
"updated": 1622197433719
}
]
}
@@ -70,8 +70,8 @@
},
{
"style": "List",
"text": "When all tasks stop may you close the console app.",
"updated": 1616416111891,
"text": "When all tasks stop you may close the console app or stop the process with Ctrl + Key-C.",
"updated": 1622197535990,
"translations": [
{
"language": "ID",
@@ -26,8 +26,8 @@
"paragraphs": [
{
"style": "Text",
"text": "The charting space lives on top of the design space, separated by a turquoise slider. As you will come to expect from Superalgos, the charting space is configurable and highly flexible. Everything that happens there is defined on the Charting Space.",
"updated": 1616416243162,
"text": "The charting space lives on top of the design space, separated by a turquoise slider. As you will come to expect from Superalgos, the charting space is configurable and highly flexible. Everything that happens there is defined on the Charting Space hierarchy.",
"updated": 1622197696958,
"translations": [
{
"language": "IT",
@@ -18,7 +18,8 @@
{
"language": "ID",
"text": "Aku akan mempercepat gerakmu dalam berkeliling dan menelusuri charting space dengan cepat... Mari coba slider duluan!",
"updated": 1616932890422
"updated": 1616932890422,
"style": "Definition"
}
]
},
@@ -36,12 +37,13 @@
{
"language": "ID",
"text": "Click disana dan drag kebawah untuk menutup design space dan membuka charting space. Lakukan sebaliknya untuk bertukar posisi. Dari keyboard gunakan Ctrl + Shift + ↓. Coba juga ↑ ← →",
"updated": 1616932984437
"updated": 1616932984437,
"style": "Callout"
}
]
},
{
"style": "Note",
"style": "Success",
"text": "Unless you need both spaces to be partially open, it's always a good idea to fully close either of them to save computing resources in your machine.",
"translations": [
{
@@ -53,7 +55,8 @@
{
"language": "ID",
"text": "Kecuali jika kamu memerlukan kedua ruang untuk dibuka sebagian, sebaiknya tutup salah satunya untuk menghemat sumber daya komputasi di Perangkat-mu.",
"updated": 1616933049943
"updated": 1616933049943,
"style": "Note"
}
]
}
@@ -26,8 +26,8 @@
"paragraphs": [
{
"style": "Text",
"text": "To keep things simple for newcomers, there are only two charts in this Getting Started Workspace. Advanced users monitor charts from multiple exchanges and multiple markets.",
"updated": 1616416713126,
"text": "To keep things simple for newcomers, there are only two charts in this Getting Started Tutorials workspace. Advanced users monitor charts from multiple exchanges and multiple markets.",
"updated": 1622198114561,
"translations": [
{
"language": "IT",
@@ -45,7 +45,7 @@
},
{
"style": "Callout",
"text": "To move around the charting space, click and drag using your mouse. <br/><br/>The keyboard combination is Shift plus the arrow keys ↑ ← → ↓",
"text": "To move around the Viewport, click and drag on the blank area using your mouse. <br/><br/>The keyboard combination is Shift plus the arrow keys ↑ ← → ↓",
"translations": [
{
"language": "IT",
@@ -59,7 +59,8 @@
"updated": 1616935011038,
"style": "Callout"
}
]
],
"updated": 1622198195729
}
]
}
@@ -18,14 +18,15 @@
{
"language": "ID",
"text": "Bagaimana membuat time machine menjadi sesuai dengan aspect ratio dari layar?",
"updated": 1616936505798
"updated": 1616936505798,
"style": "Definition"
}
]
},
"paragraphs": [
{
"style": "Text",
"text": "Matching the aspect ratio of your time machines to the aspect ratio of your screen is crucial for charts to fit your screen tightly!",
"text": "Matching the aspect ratio of your time machines to the aspect ratio of your screen is crucial for charts to fit your screen tightly while zooming in!",
"translations": [
{
"language": "IT",
@@ -36,14 +37,16 @@
{
"language": "ID",
"text": "Mencocokkan rasio aspek time machine kamu dengan rasio aspek laya sangat penting agar bagan pas dengan layarmu!",
"updated": 1616936545221
"updated": 1616936545221,
"style": "Text"
}
]
],
"updated": 1622198491208
},
{
"style": "Callout",
"text": "Point your mouse at one of the time machines and hit Ctrl + Shift + Key-A. Do the same with the other one!",
"updated": 1610134929741,
"text": "Direct your mouse at one of the time machines and hit Ctrl + Shift + Key-A. Do the same with the other one!",
"updated": 1622198768797,
"translations": [
{
"language": "IT",
@@ -54,7 +57,8 @@
{
"language": "ID",
"text": "Point mousemu ke satu dari time machines dan tekan Ctrl + Shift + Key-A. Lakukan dengan yang satunya juga!",
"updated": 1616936593204
"updated": 1616936593204,
"style": "Callout"
}
]
},
@@ -72,7 +76,8 @@
{
"language": "ID",
"text": "Biarkan dua time machine cocok dengan rasio aspek layarmu. dari sekarang!",
"updated": 1616936619368
"updated": 1616936619368,
"style": "Success"
}
]
}
@@ -27,8 +27,8 @@
"paragraphs": [
{
"style": "List",
"text": "Adjust the aspect ratio: Point your mouse to the chart and hit Ctrl + Shift + Key-A",
"updated": 1616418151629,
"text": "Adjust the aspect ratio: Point your mouse to the Backtesting Session chart (the one on top) and hit Ctrl + Shift + Key-A",
"updated": 1622198971565,
"translations": [
{
"language": "ID",
@@ -71,7 +71,7 @@
},
{
"style": "List",
"text": "Double-click again: this takes you further in the chart, to the zoom level in which the chart perfectly fits the screen and layer managers emerge.",
"text": "Double-click again: this takes you further in the chart, to the zoom level in which the chart perfectly fits the screen and Layer Managers emerge.",
"translations": [
{
"language": "IT",
@@ -86,7 +86,7 @@
"style": "List"
}
],
"updated": 1616418383322
"updated": 1622198926988
}
]
}
@@ -32,7 +32,7 @@
},
{
"style": "Callout",
"text": "To toggle between the various automatic modes and manual mode, hit Shift and make a gentle one-step roll with the wheel of your mouse on top of the time scale box. Alternatively, you can also place the mouse pointer over the scale box and hit the up and down arrow keys ↑ ↓. ",
"text": "To toggle between the various automatic modes and manual mode, hit Shift and make a gentle one-step roll with the wheel of your mouse on top of the time scale box. Alternatively, you can also place the mouse pointer over the scale box and hit the up and down arrow keys ↑ ↓.",
"translations": [
{
"language": "IT",
@@ -41,7 +41,7 @@
"style": "Callout"
}
],
"updated": 1616495659408
"updated": 1622199287763
},
{
"style": "Text",
@@ -51,7 +51,8 @@
{
"language": "IT",
"text": "Dovresti poterti muovere liberamente sull'asse X del grafico, ossia quella del tempo.",
"updated": 1618647843971
"updated": 1618647843971,
"style": "Text"
}
]
}
@@ -32,8 +32,8 @@
},
{
"style": "Text",
"text": "I hope the structure of nodes is intuitive enough to grasp how powerful the concept of the Design Space is. You set up a time machine by adding Timeline Chart nodes and the desired scales. Then set up layer managers and layers referencing the corresponding Data Mine Products so that the desired data becomes available on a particular layer manager on the charts. It's like the Legoland® of trading charts!",
"updated": 1616427563290,
"text": "I hope the structure of nodes is intuitive enough to grasp how powerful the concept of the Design Space is. You set up a time machine by adding Timeline Chart nodes and the desired scales. Then set up layer managers and layers referencing the corresponding Data Mine Products so that the desired data becomes available on a particular layer manager on the charts. It's like the Legoland® of trading charts! You'll learn to cutomize charts later on!",
"updated": 1622200261142,
"translations": [
{
"language": "IT",
@@ -7,14 +7,16 @@
"project": "Superalgos",
"name": "network-node"
},
"text": "Picture an army of bots working with multiple exchanges, markets, and strategies, running on a network ala trading farm.",
"text": "Picture an army of bots working with multiple exchanges, markets, and strategies, running on a network <i>à la</i> trading farm.",
"translations": [
{
"language": "IT",
"text": "Immagina un esercito di bots che lavorano con vari exchange, mercati e strategie, coordinati da un network che fa da trading farm.",
"updated": 1618057758985
"updated": 1618057758985,
"style": "Definition"
}
]
],
"updated": 1622200549490
},
"paragraphs": [
{
@@ -25,7 +27,8 @@
{
"language": "IT",
"text": "Il Network Node fa esattamente questo. I processi che hai visto finora girano su una singola macchina. Però...",
"updated": 1618057806513
"updated": 1618057806513,
"style": "Text"
}
]
},
@@ -37,7 +40,8 @@
{
"language": "IT",
"text": "Superalgos permette di distribuire e coordinare tasks attraverso una rete di macchine che eseguono il Client! Questo permette di eseguire operazioni avanzate e scalabili. Qualsiasi macchina che esegue la GUI può controllare il tutto!",
"updated": 1618057957707
"updated": 1618057957707,
"style": "Callout"
}
]
},
@@ -48,7 +52,8 @@
{
"language": "IT",
"text": "Puoi creare network arbitrariamente complessi che vanno da qualche Raspberry Pi a un datacenter industriale.",
"updated": 1618058007870
"updated": 1618058007870,
"style": "Text"
}
]
}
@@ -7,14 +7,16 @@
"project": "Superalgos",
"name": "under-construction"
},
"text": "Please, do not be surprised to find an under construction sign here and there...",
"text": "Don't be surprised if you find an under construction sign here and there...",
"translations": [
{
"language": "IT",
"text": "Non sorprenderti se trovi segnali di \"lavori in corso\" qua e là...",
"updated": 1618059716381
"updated": 1618059716381,
"style": "Definition"
}
]
],
"updated": 1622200773527
},
"paragraphs": [
{
@@ -24,7 +26,8 @@
{
"language": "IT",
"text": "Come detto prima, Superalgos è in continua evoluzione e gli sviluppi per la versione successiva potrebbero essere occasionalmente implementati nella versione corrente, per risolvere problemi o apportare piccole migliorie.",
"updated": 1618059772511
"updated": 1618059772511,
"style": "Text"
}
]
},
@@ -35,7 +38,8 @@
{
"language": "IT",
"text": "Se vuoi scoprire cosa bolle in pentola per la prossima release di Superalgos, unisciti al canale Telegram Superalgos Develop.",
"updated": 1618059823365
"updated": 1618059823365,
"style": "Callout"
}
]
}
@@ -12,7 +12,8 @@
{
"language": "IT",
"text": "Forza, iniziamo! Sarà comunque una cosa veloce, perchè stiamo testando dati di una sola giornata.",
"updated": 1618060660046
"updated": 1618060660046,
"style": "Definition"
}
]
},
@@ -24,7 +25,8 @@
{
"language": "IT",
"text": "Eseguire una task di trading è simile a eseguire una task di data mining. La differenza sta nel fatto che, dopo aver lanciato la task, devi anche lanciare la trading session.",
"updated": 1618060706178
"updated": 1618060706178,
"style": "Text"
}
]
},
@@ -36,20 +38,23 @@
{
"language": "IT",
"text": "Seleziona Run dal menu Task, e poi seleziona Run dal menu della Backtesting Session!",
"updated": 1618060790679
"updated": 1618060790679,
"style": "Callout"
}
]
},
{
"style": "Note",
"text": "When the progress notice of the Trading Process Instance get's to the 100% mark, stop the task and click Next.",
"text": "When the Backtesting Session indicates it finished processing, stop the Task and click Next.",
"translations": [
{
"language": "IT",
"text": "Quando la progress bar della Trading Process Instance raggiunge il 100%, ferma la task e clicca Next.",
"updated": 1618060849542
"updated": 1618060849542,
"style": "Note"
}
]
],
"updated": 1622201246283
}
]
}
@@ -12,7 +12,8 @@
{
"language": "IT",
"text": "Abbiamo lanciato un backtest ma non abbiamo discusso del Trading System che stiamo testando! Facciamolo ora!",
"updated": 1618061084694
"updated": 1618061084694,
"style": "Definition"
}
]
},
@@ -25,7 +26,8 @@
{
"language": "IT",
"text": "L'idea è comprare il \"falling knife\" e vendere il \"rebound\". La strategia piazza un Limit Buy Order al di sotto dell'attuale prezzo. Se l'ordine non viene evaso nel giro del minuto successivo, viene cancellato e ne viene creato uno nuovo, eventualmente a un prezzo migliore. Se il prezzo scende, è probabile che l'ordine venga evaso: a quel punto la strategia tenta di vendere a un prezzo maggiore.",
"updated": 1618061264322
"updated": 1618061264322,
"style": "Text"
}
]
},
@@ -35,13 +37,14 @@
},
{
"style": "Note",
"text": "Let's not discuss the merits of the trading idea but the implementation. This is just a demo to show off the capacities of the Trading Bot, not the strategy per se.",
"updated": 1610640921014,
"text": "Let's not discuss the merits of the trading idea but the implementation. This is just a demo to show off the capacities of the Trading Bot, not the strategy <i>per se</i>.",
"updated": 1622201574916,
"translations": [
{
"language": "IT",
"text": "Non discutiamo dell'efficacia del metodo, ma della sua implementazione. Questa è una demo per mostrare le capacità del Trading Bot, non la strategia in sè.",
"updated": 1618061327170
"updated": 1618061327170,
"style": "Note"
}
]
}
@@ -386,10 +386,11 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) {
}
let separator = ""
pathString = '/'
parametersMap.forEach(addParameterToPath)
function addParameterToPath(value, key, map) {
if (pathString === "") { pathString = '/' }
let apiPathParameter = value
let parameterValue = key // This is the default value
if (apiPathParameter.config.replaceBy !== undefined) {
@@ -517,7 +518,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) {
Now that we have the endpointNode, the parameters and all the information
needed to place the call to the API.
*/
let httpClient = require('https')
const fetch = require('node-fetch')
let url = protocol + '://' +
hostName +
portNumber +
@@ -532,140 +533,192 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) {
This is how we call the API.
*/
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[INFO] start -> startProcess -> fetchAPIData -> httpClient.get -> url = " + url)
"[INFO] start -> startProcess -> fetchAPIData -> url = " + url)
httpClient.get(url, (response) => {
fetch(url)
.then((response) => {
const chunks = []
let apiResponseSchemaNode
let errorCodeReceived
let apiResponseSchemaNode
let errorCodeReceived
/*
At this point we have received the first http reponse from the API server,
and from it we can extract the status code, which is the html code of the
response of our request.
With that code we can get the API Response Schema, which will tell us how
to extract data from the response.
*/
getApiResponseSchema(response.statusCode)
if (apiResponseSchemaNode === undefined) {
errorCodeReceived = true
TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException(
processIndex,
MODULE_NAME,
'API Data Fetcher Bot',
{ resposeCodeReceived: response.statusCode, detais: 'The response code ' + response.statusCode + ' received is not associated with any API Query Response node.' },
'Unexpected API Response Code',
endpointNode
)
}
function getApiResponseSchema(responseCode) {
/*
The API Response Schema we will depend on the response code received from the
API server. Here we will locate the right Api Response Schema.
At this point we have received the first http reponse from the API server,
and from it we can extract the status code, which is the html code of the
response of our request.
With that code we can get the API Response Schema, which will tell us how
to extract data from the response.
*/
for (let j = 0; j < apiMap.apiVersions.length; j++) {
let version = apiMap.apiVersions[j]
for (let k = 0; k < version.apiEndpoints.length; k++) {
let endpoint = version.apiEndpoints[k]
if (endpointNode.id === endpoint.id) {
for (let i = 0; i < endpoint.apiQueryResponses.apiQueryResponses.length; i++) {
let apiQueryResponse = endpoint.apiQueryResponses.apiQueryResponses[i]
getApiResponseSchema(response.status)
if (Number(apiQueryResponse.config.codeName) === responseCode) {
apiResponseSchemaNode = apiQueryResponse.apiResponseSchema
if (apiResponseSchemaNode === undefined) {
errorCodeReceived = true
TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException(
processIndex,
MODULE_NAME,
'API Data Fetcher Bot',
{ resposeCodeReceived: response.status, errorDetails: 'Calling the URL ' + url + '. The response code ' + response.status + ' received is not associated with any API Query Response node.' },
'Unexpected API Response Code',
endpointNode
)
} else {
getResponseBody()
}
/*
We will check that what we received is not an error code.
*/
if (apiQueryResponse.config.isError === true) {
errorCodeReceived = true
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> getApiResponseSchema -> API Response is an Error -> responseCode = " + responseCode)
function getApiResponseSchema(responseCode) {
/*
The API Response Schema we will depend on the response code received from the
API server. Here we will locate the right Api Response Schema.
*/
for (let j = 0; j < apiMap.apiVersions.length; j++) {
let version = apiMap.apiVersions[j]
for (let k = 0; k < version.apiEndpoints.length; k++) {
let endpoint = version.apiEndpoints[k]
if (endpointNode.id === endpoint.id) {
for (let i = 0; i < endpoint.apiQueryResponses.apiQueryResponses.length; i++) {
let apiQueryResponse = endpoint.apiQueryResponses.apiQueryResponses[i]
if (Number(apiQueryResponse.config.codeName) === responseCode) {
apiResponseSchemaNode = apiQueryResponse.apiResponseSchema
/*
We will check that what we received is not an error code.
*/
if (apiQueryResponse.config.isError === true) {
errorCodeReceived = true
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> getApiResponseSchema -> API Response is an Error -> responseCode = " + responseCode)
}
return
}
return
}
}
}
}
}
}
response.on('data', (chunk) => {
chunks.push(chunk)
});
response.on('end', (d) => {
apiResponseReceivedText = Buffer.concat(chunks).toString('utf8')
/*
If we received an errror code, we abort the processing at this point.
*/
if (errorCodeReceived === true) {
resolve('ERROR_CODE_RECEIVED')
return
}
/*
Here we will validate that the overall format is what we are expecting.
*/
switch (apiResponseSchemaNode.apiResponseFields.config.fieldType) {
case 'object': {
function getResponseBody() {
response.text().then(body => {
apiResponseReceivedText = body
/*
If we did not received an object, that probably means something is not
good, and we got an HTML with the reason inside.
If we received an errror code, we abort the processing at this point.
*/
if (apiResponseReceivedText.substring(0, 1) !== "{") {
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an JSON Object. -> apiResponseReceivedText = " + apiResponseReceivedText)
resolve('UNEXPECTED_API_RESPONSE')
if (errorCodeReceived === true) {
resolve('ERROR_CODE_RECEIVED')
return
}
break
}
case 'array': {
/*
If we did not received an array, that probably means something is not
good, and we got an HTML with the reason inside.
Here we will validate that the overall format is what we are expecting.
*/
if (apiResponseReceivedText.substring(0, 1) !== "[") {
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an Array with Data. -> apiResponseReceivedText = " + apiResponseReceivedText)
resolve('UNEXPECTED_API_RESPONSE')
switch (apiResponseSchemaNode.apiResponseFields.config.fieldType) {
case 'object': {
/*
If we did not received an object, that probably means something is not
good, and we got an HTML with the reason inside.
*/
if (apiResponseReceivedText.substring(0, 1) !== "{") {
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an JSON Object. -> apiResponseReceivedText = " + apiResponseReceivedText)
resolve('UNEXPECTED_API_RESPONSE')
return
}
break
}
case 'array': {
/*
If we did not received an array, that probably means something is not
good, and we got an HTML with the reason inside.
*/
if (apiResponseReceivedText.substring(0, 1) !== "[") {
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an Array with Data. -> apiResponseReceivedText = " + apiResponseReceivedText)
resolve('UNEXPECTED_API_RESPONSE')
return
}
break
}
}
/*
The actual data we need could be anywhere within the data structure received.
The exact place is configured at the apiResponseSchemaNode property nodePath.
We will eval the nodePath property (this assumes that the apiResponseReceivedObject is defined)
*/
apiResponseReceivedObject = JSON.parse(apiResponseReceivedText)
apiData = eval(apiResponseSchemaNode.config.nodePath)
/*
We will expect the apiData to be an Array. Depending if it has data or not we will return
NO_MORE_PAGES or PAGE_FETCHED so that pagination procedure knows when to stop.
*/
if (apiData.length === 0) {
resolve('NO_MORE_PAGES')
} else {
resolve('PAGE_FETCHED')
}
/*
If we received an errror code, we abort the processing at this point.
*/
if (errorCodeReceived === true) {
resolve('ERROR_CODE_RECEIVED')
return
}
break
}
/*
Here we will validate that the overall format is what we are expecting.
*/
switch (apiResponseSchemaNode.apiResponseFields.config.fieldType) {
case 'object': {
/*
If we did not received an object, that probably means something is not
good, and we got an HTML with the reason inside.
*/
if (apiResponseReceivedText.substring(0, 1) !== "{") {
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an JSON Object. -> apiResponseReceivedText = " + apiResponseReceivedText)
resolve('UNEXPECTED_API_RESPONSE')
return
}
break
}
case 'array': {
/*
If we did not received an array, that probably means something is not
good, and we got an HTML with the reason inside.
*/
if (apiResponseReceivedText.substring(0, 1) !== "[") {
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an Array with Data. -> apiResponseReceivedText = " + apiResponseReceivedText)
resolve('UNEXPECTED_API_RESPONSE')
return
}
break
}
}
/*
The actual data we need could be anywhere within the data structure received.
The exact place is configured at the apiResponseSchemaNode property nodePath.
We will eval the nodePath property (this assumes that the apiResponseReceivedObject is defined)
*/
apiResponseReceivedObject = JSON.parse(apiResponseReceivedText)
apiData = eval(apiResponseSchemaNode.config.nodePath)
/*
We will expect the apiData to be an Array. Depending if it has data or not we will return
NO_MORE_PAGES or PAGE_FETCHED so that pagination procedure knows when to stop.
*/
if (apiData.length === 0) {
resolve('NO_MORE_PAGES')
} else {
resolve('PAGE_FETCHED')
}
})
}
/*
The actual data we need could be anywhere within the data structure received.
The exact place is configured at the apiResponseSchemaNode property nodePath.
We will eval the nodePath property (this assumes that the apiResponseReceivedObject is defined)
*/
apiResponseReceivedObject = JSON.parse(apiResponseReceivedText)
apiData = eval(apiResponseSchemaNode.config.nodePath)
/*
We will expect the apiData to be an Array. Depending if it has data or not we will return
NO_MORE_PAGES or PAGE_FETCHED so that pagination procedure knows when to stop.
*/
if (apiData.length === 0) {
resolve('NO_MORE_PAGES')
} else {
resolve('PAGE_FETCHED')
}
});
}).on('error', (err) => {
console.error(err);
TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[ERROR] start -> httpClient.get -> err = " + err.stack)
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[ERROR] start -> httpClient.get -> Connection to the API Server Failed. Maybe there is no Internet connection. Retrying later. ")
resolve('NO_CONNECTION')
});
})
.catch(err => {
TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[ERROR] start -> fetch -> err = " + err.stack)
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME,
"[ERROR] start -> fetch -> Connection to the API Server Failed. Maybe there is no Internet connection. Retrying later. ")
resolve('NO_CONNECTION')
})
}
)
@@ -947,7 +1000,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) {
/*
We will need to get the nodePath for this property, representing the path
to the value on the received data. There are 2 ways to get this nodePath.
1) It is explicitly declared at the node. If this exists then we will use it.
2) It was calculated automatically.
*/
@@ -1009,10 +1062,16 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) {
thisReport.file = {
lastRun: (new Date()).toISOString(),
lastPage: lastPage,
lastFile: contextVariables.lastFile.toISOString(),
beginingOfMarket: contextVariables.beginingOfMarket
}
/*
For Single-File Datasets there is no lastFile defined.
*/
if (contextVariables.lastFile !== undefined) {
thisReport.file.lastFile = contextVariables.lastFile.toISOString()
}
if (thisReport.file.beginingOfMarket === undefined) {
thisReport.file.beginingOfMarket = (new Date()).toISOString()
}
@@ -0,0 +1,11 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
}
}
}
@@ -329,7 +329,7 @@
'Project/' +
TS.projects.superalgos.globals.taskConstants.PROJECT_DEFINITION_NODE.config.codeName + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.type.replace(' ', '-') + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName + "/" +
'Candles' + "/" +
"Candles-Volumes" + '/' + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "-" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName
@@ -375,7 +375,7 @@
'Project/' +
TS.projects.superalgos.globals.taskConstants.PROJECT_DEFINITION_NODE.config.codeName + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.type.replace(' ', '-') + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName + "/" +
'Candles' + "/" +
"Candles-Volumes" + '/' + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "-" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName
@@ -69,7 +69,7 @@
let filePathRoot =
'Project/' + TS.projects.superalgos.globals.taskConstants.PROJECT_DEFINITION_NODE.config.codeName + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.type.replace(' ', '-') + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName + "/" +
'Candles' + "/" +
"Candles-Volumes" + '/' + TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.config.codeName + "/" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + "-" +
TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName
@@ -178,7 +178,7 @@ exports.newSuperalgosBotModulesTradingPosition = function (processIndex) {
tradingEngine.tradingCurrent.position.takeProfit.takeProfitPhase.value = phase
}
function initialTargets(tradingSystemStageNode, tradingEngineStageNode) {
function initialTargets(tradingSystemStageNode, tradingEngineStageNode, stageName) {
if (tradingSystemStageNode.initialTargets === undefined) {
const message = 'Initial Targets Node Missing'
@@ -194,7 +194,7 @@ exports.newSuperalgosBotModulesTradingPosition = function (processIndex) {
}
setTargetRate()
setTargetSize()
return setTargetSize(stageName)
function setTargetRate() {
if (tradingSystemStageNode.initialTargets.targetRate === undefined) {
@@ -262,7 +262,7 @@ exports.newSuperalgosBotModulesTradingPosition = function (processIndex) {
}
}
function setTargetSize() {
function setTargetSize(stageName) {
/* Basic Validation */
if (
tradingSystemStageNode.initialTargets.targetSizeInBaseAsset !== undefined &&
@@ -298,6 +298,9 @@ exports.newSuperalgosBotModulesTradingPosition = function (processIndex) {
badDefinitionUnhandledException(undefined, message, tradingSystemStageNode.initialTargets.targetSizeInBaseAsset, docs)
}
if (value === 0) {
if (stageName === 'Close Stage') {
return false;
}
const message = 'Target Size Value Zero'
let docs = {
@@ -266,7 +266,8 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
function checkIfWeNeedToAbortTheStage() {
/* Abort Open Stage Check */
if (tradingEngine.tradingCurrent.strategyOpenStage.status.value === 'Open' && tradingEngine.tradingCurrent.strategyCloseStage.status.value === 'Open') {
if (tradingEngine.tradingCurrent.strategyOpenStage.status.value === 'Open' &&
(tradingEngine.tradingCurrent.strategyCloseStage.status.value === 'Opening' || tradingEngine.tradingCurrent.strategyCloseStage.status.value === 'Open') ){
/*
if the Close stage is opened while the open stage is still open that means that
we need to stop placing orders, check what happened to the orders already placed,
@@ -281,7 +282,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
if (tradingEngine.tradingCurrent.strategyOpenStage.status.value === 'Opening') {
/*
The system allows the user not to define an Open Stage, because the Open Stage is optional.
Here we are going to see if that is the case and if it is, we will inmidiatelly consider
Here we are going to see if that is the case and if it is, we will immediately consider
the Open Stage as closed.
*/
if (tradingSystem.tradingStrategies[tradingEngine.tradingCurrent.strategy.index.value].openStage === undefined) {
@@ -427,7 +428,9 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
*/
if (manageStage === undefined) {
changeStageStatus('Manage Stage', 'Closed', 'Manage Stage Undefined')
changeStageStatus('Close Stage', 'Opening')
if (tradingEngine.tradingCurrent.strategyOpenStage.status.value !== 'Open' && tradingEngine.tradingCurrent.strategyOpenStage.status.value !== 'Opening') {
changeStageStatus('Close Stage', 'Opening');
}
return
}
@@ -766,7 +769,7 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
or our Take Profit were hit.
*/
/* Stop Loss condition: Here we verify if the Stop Loss was hitted or not. */
/* Stop Loss condition: Here we verify if the Stop Loss was hit or not. */
if (
(
tradingEngine.tradingCurrent.position.stopLoss.stopLossPosition.value === 'Above' &&
@@ -838,7 +841,9 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
/* Exit Position size and rate */
tradingSystem.evalFormulas(tradingSystemStage, 'Initial Targets')
tradingPositionModuleObject.initialTargets(tradingSystemStage, tradingEngine.tradingCurrent.strategyCloseStage)
if (tradingPositionModuleObject.initialTargets(tradingSystemStage, tradingEngine.tradingCurrent.strategyCloseStage, 'Close Stage') === false) {
//console.log("No Close-Stage Target Asset to Trade: Strategy Closing.");
}
initializeStageTargetSize()
changeStageStatus('Close Stage', 'Open')
@@ -955,9 +960,9 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
function exitPositionValidation() {
/*
Exit Position Validation: we need al the previous stages to be either closed
or at their initial default value. The last is becasue after Closed objects are
initialized to their defualts.
Exit Position Validation: we need all the previous stages to be either closed
or at their initial default value. The last is because after Closed objects are
initialized to their defaults.
*/
if (tradingEngine.tradingCurrent.position.status.value !== 'Open' && tradingEngine.tradingCurrent.position.status.value !== 'Closing') { return }
if (tradingEngine.tradingCurrent.position.status.value !== 'Close' && tradingEngine.tradingCurrent.position.status.value !== 'Closing') { return }
@@ -1145,8 +1150,8 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
checkUserDefinedCode(stageName, 'Open')
}
if (stage.status.value === 'Closed') {
closeStage(stage)
checkUserDefinedCode(stageName, 'Closed')
closeStage(stage, stageName)
}
/*
@@ -1167,10 +1172,23 @@ exports.newSuperalgosBotModulesTradingStages = function (processIndex) {
stage.beginRate.value = tradingEngine.tradingCurrent.tradingEpisode.candle.close.value
}
function closeStage(stage) {
function closeStage(stage, stageName) {
/* Recording the closing at the Trading Engine Data Structure */
stage.end.value = tradingEngine.tradingCurrent.tradingEpisode.cycle.lastEnd.value
stage.endRate.value = tradingEngine.tradingCurrent.tradingEpisode.candle.close.value
if (stageName === 'Open Stage') {
if (tradingEngine.tradingCurrent.strategyCloseStage.status.value !== 'Opening' && tradingEngine.tradingCurrent.strategyCloseStage.status.value !== 'Open' &&
tradingEngine.tradingCurrent.strategyManageStage.status.value !== 'Opening' && tradingEngine.tradingCurrent.strategyManageStage.status.value !== 'Open') {
changeStageStatus('Close Stage', 'Opening');
}
}
if (stageName === 'Close Stage') {
if (tradingEngine.tradingCurrent.position.status.value === 'Open') {
tradingPositionModuleObject.closingPosition('Close Stage Closed')
/* NOTE:TODO: Announcement May need added Here */
}
}
}
}
@@ -171,10 +171,10 @@ function newSuperalgosTutorialSpace() {
) {
if (config.toggleMapView.view === "On") {
UI.projects.superalgos.spaces.floatingSpace.inMapMode = true
} else
if (config.toggleMapView.view === "Off") {
UI.projects.superalgos.spaces.floatingSpace.inMapMode = false
}
} else
if (config.toggleMapView.view === "Off") {
UI.projects.superalgos.spaces.floatingSpace.inMapMode = false
}
}
}
function checkViewportZoom() {
@@ -779,7 +779,20 @@ function newSuperalgosTutorialSpace() {
resetAfterButtonPressed()
checkForceFocus()
if (navigationStack.length > 1) {
let previousNode = navigationStack[navigationStack.length - 2]
let tutorial = {
status: undefined
}
let previousNode
/*
Reseet the Status of Current and Previous Node
so that RESUME goes to the right node.
*/
UI.projects.superalgos.utilities.tutorial.saveTutorial(currentNode.payload, tutorial)
previousNode = navigationStack[navigationStack.length - 3]
if (previousNode !== undefined) {
UI.projects.superalgos.utilities.tutorial.saveTutorial(previousNode.payload, tutorial)
}
previousNode = navigationStack[navigationStack.length - 2]
switch (previousNode.type) {
case 'Tutorial': {
currentNode = previousNode
@@ -825,7 +838,7 @@ function newSuperalgosTutorialSpace() {
resetDocumentation()
resetRepositionAtTimeMachine()
resetPositionAtNode()
resetTimeMachineKeyPressed()
resetTimeMachineKeyPressed()
resetKeyPressed()
resetSlider()
changeNodeConfig()
@@ -907,7 +920,7 @@ function newSuperalgosTutorialSpace() {
}
function playTutorial(node) {
if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true ) { return }
if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true) { return }
PAGE_NUMBER = 0
TUTORIAL_NAME = node.name
@@ -922,7 +935,7 @@ function newSuperalgosTutorialSpace() {
}
function resumeTutorial(node) {
if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true ) { return }
if (UI.projects.superalgos.spaces.designSpace.workspace.isInitialized !== true) { return }
navigationStack = []
node.payload.uiObject.isPlaying = true
@@ -1045,7 +1058,6 @@ function newSuperalgosTutorialSpace() {
return
}
function findNextNode(node) {
if (node.tutorialSteps !== undefined) {
for (let i = 0; i < node.tutorialSteps.length; i++) {
@@ -1064,11 +1076,11 @@ function newSuperalgosTutorialSpace() {
status: undefined
}
UI.projects.superalgos.utilities.tutorial.loadTutorial(tutorialStep.payload, tutorial)
currentNode = tutorialStep
currentStatus = 'Playing Step'
navigationStack.push(currentNode)
if (tutorial.status !== 'Done') {
currentNode = tutorialStep
currentStatus = 'Playing Step'
advanced = true
navigationStack.push(currentNode)
findTutorialNode(currentNode)
return
}
@@ -1100,11 +1112,11 @@ function newSuperalgosTutorialSpace() {
status: undefined
}
UI.projects.superalgos.utilities.tutorial.loadTutorial(tutorialTopic.payload, tutorial)
currentNode = tutorialTopic
currentStatus = 'Playing Topic'
navigationStack.push(currentNode)
if (tutorial.status !== 'Done') {
currentNode = tutorialTopic
currentStatus = 'Playing Topic'
advanced = true
navigationStack.push(currentNode)
findTutorialNode(currentNode)
return
}
@@ -1139,11 +1151,11 @@ function newSuperalgosTutorialSpace() {
status: undefined
}
UI.projects.superalgos.utilities.tutorial.loadTutorial(tutorialTopic.payload, tutorial)
currentNode = tutorialTopic
currentStatus = 'Playing Topic'
navigationStack.push(currentNode)
if (tutorial.status !== 'Done') {
currentNode = tutorialTopic
currentStatus = 'Playing Topic'
advanced = true
navigationStack.push(currentNode)
findTutorialNode(currentNode)
return
}
@@ -1215,7 +1227,7 @@ function newSuperalgosTutorialSpace() {
if (nodeConfig.controlDocs !== undefined) {
if (nodeConfig.controlDocs.closeTutorialEditor !== true) {
UI.projects.superalgos.spaces.docsSpace.navigateTo(nodeConfig.docs.project, 'Tutorial', nodeConfig.docs.type)
}
}
if (nodeConfig.controlDocs.searchPage === true) {
UI.projects.superalgos.spaces.docsSpace.searchPage()
}
+1
View File
@@ -25,6 +25,7 @@ if (process.argv.includes("noShortcuts")) {
let nodeModulesDirs = [
path.join( process.cwd(), "Client"),
path.join( process.cwd(), "Projects", "Superalgos", "TS", "Bot-Modules", "Sensor-Bot", "Exchange-Raw-Data"),
path.join( process.cwd(), "Projects", "Superalgos", "TS", "Bot-Modules", "API-Data-Fetcher-Bot"),
path.join( process.cwd(), "Projects", "Superalgos", "TS", "Bot-Modules", "Trading-Bot", "Announcements"),
path.join( process.cwd(), "Projects", "Superalgos", "TS", "Bot-Modules", "Trading-Bot", "Low-Frequency-Trading", "APIs"),
path.join( process.cwd(), "Projects", "Superalgos", "TS", "Task-Modules"),