Merge pull request #164 from Superalgos/develop
Release to Master Branch
This commit is contained in:
2055 files changed
+251027
-166317
No files matched your search
@@ -33,6 +33,9 @@ PATH_TO_CANVAS_APP=./CanvasApp
|
||||
PATH_TO_FILES_COMPONENT=./Files-Component/src
|
||||
PATH_TO_WEB_SERVER=./WebServer/
|
||||
|
||||
APP_SCHEMA_PATH=./
|
||||
WORKSPACE_PATH=./
|
||||
|
||||
GATEWAY_ENDPOINT=https://demo-api-dev.superalgos.org/graphql
|
||||
|
||||
|
||||
+361
-57
@@ -786,14 +786,6 @@
|
||||
{
|
||||
"type": "Condition",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Edit Condition",
|
||||
"label": "Edit Condition",
|
||||
"iconPathOn": "html",
|
||||
"iconPathOff": "html",
|
||||
"dontShowAtFullscreen": true,
|
||||
"actionFunction": "uiObject.conditionEditor.activate"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
@@ -1115,7 +1107,7 @@
|
||||
"addLeftIcons": true,
|
||||
"level": 4,
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Market->"
|
||||
"compatibleTypes": "->Super Actions->Market->"
|
||||
},
|
||||
"referenceAttachesTo": {
|
||||
"compatibleTypes": "->Master Script->"
|
||||
@@ -1147,6 +1139,7 @@
|
||||
"addLeftIcons": true,
|
||||
"level": 1,
|
||||
"icon": "network",
|
||||
"docURL": "https://docs.superalgos.org/suite-network-hierarchy.html#network",
|
||||
"properties": [
|
||||
{
|
||||
"name": "networkNodes",
|
||||
@@ -1278,7 +1271,7 @@
|
||||
"addLeftIcons": true,
|
||||
"level": 1,
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Data Mining->Testing Environment->Production Environment->Template Structure->"
|
||||
"compatibleTypes": "->Exchange Tasks->Template Structure->"
|
||||
},
|
||||
"icon": "task-manager",
|
||||
"properties": [
|
||||
@@ -1788,7 +1781,7 @@
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Parameters->"
|
||||
},
|
||||
"icon": "loading",
|
||||
"icon": "asset",
|
||||
"alternativeIcons": "Use Reference Grandparent",
|
||||
"title": [
|
||||
"Use Reference Grandparent"
|
||||
@@ -1830,7 +1823,7 @@
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Parameters->"
|
||||
},
|
||||
"icon": "loading",
|
||||
"icon": "asset",
|
||||
"alternativeIcons": "Use Reference Grandparent",
|
||||
"title": [
|
||||
"Use Reference Grandparent"
|
||||
@@ -1859,7 +1852,7 @@
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Market->"
|
||||
},
|
||||
"icon": "loading",
|
||||
"icon": "asset",
|
||||
"alternativeIcons": "Use Reference Parent",
|
||||
"title": [
|
||||
"Use Reference Parent"
|
||||
@@ -1888,7 +1881,7 @@
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Market->"
|
||||
},
|
||||
"icon": "loading",
|
||||
"icon": "asset",
|
||||
"alternativeIcons": "Use Reference Parent",
|
||||
"title": [
|
||||
"Use Reference Parent"
|
||||
@@ -2504,6 +2497,9 @@
|
||||
},
|
||||
"level": 2,
|
||||
"icon": "data-mine",
|
||||
"initialValues": {
|
||||
"code": "{ \n\"codeName\": \"Write here a name with no spaces or dashes.\"\n}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "sensorBots",
|
||||
@@ -2770,6 +2766,11 @@
|
||||
"editors": {
|
||||
"config": true
|
||||
},
|
||||
"isTitleAllwaysVisible": true,
|
||||
"title": [
|
||||
"Use Reference Parent Parent Parent",
|
||||
"Use Reference Parent Parent"
|
||||
],
|
||||
"level": 3,
|
||||
"referenceAttachesTo": {
|
||||
"compatibleTypes": "->Status Report->"
|
||||
@@ -3055,6 +3056,11 @@
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"isTitleAllwaysVisible": true,
|
||||
"title": [
|
||||
"Use Reference Parent Parent",
|
||||
"Use Reference Parent"
|
||||
],
|
||||
"addLeftIcons": true,
|
||||
"level": 3,
|
||||
"referenceAttachesTo": {
|
||||
@@ -4426,12 +4432,18 @@
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
"propertyToCheckFor": "cryptoExchanges",
|
||||
"label": "Add Crypto Exchanges",
|
||||
"relatedUiObject": "Crypto Exchanges",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
"propertyToCheckFor": "superActions",
|
||||
"label": "Add Super Actions",
|
||||
"relatedUiObject": "Super Actions",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
@@ -4449,8 +4461,48 @@
|
||||
"properties": [
|
||||
{
|
||||
"name": "cryptoExchanges",
|
||||
"type": "array",
|
||||
"childType": "Crypto Exchanges"
|
||||
},
|
||||
{
|
||||
"name": "superActions",
|
||||
"type": "node",
|
||||
"childType": "Network Node"
|
||||
"childType": "Super Actions"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Super Actions",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Super Action",
|
||||
"relatedUiObject": "Super Action",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Delete",
|
||||
"label": "Delete Super Actions",
|
||||
"iconPathOn": "delete",
|
||||
"iconPathOff": "delete",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"propertyNameAtParent": "superActions",
|
||||
"isTitleAllwaysVisible": false,
|
||||
"addLeftIcons": true,
|
||||
"level": 3,
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Crypto Ecosystem->"
|
||||
},
|
||||
"icon": "super-action",
|
||||
"properties": [
|
||||
{
|
||||
"name": "superActions",
|
||||
"type": "array",
|
||||
"childType": "Super Action"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -4463,6 +4515,15 @@
|
||||
"relatedUiObject": "Crypto Exchange",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Add Missing Crypto Exchanges",
|
||||
"label": "Add Missing Exchanges",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Proceed",
|
||||
"workDoneLabel": "Done",
|
||||
"relatedUiObject": "Crypto Exchange",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
@@ -4473,6 +4534,7 @@
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"isTitleAllwaysVisible": true,
|
||||
"addLeftIcons": true,
|
||||
"level": 1,
|
||||
"icon": "crypto-exchanges",
|
||||
@@ -4569,43 +4631,43 @@
|
||||
],
|
||||
"alternativeIcons": [
|
||||
{
|
||||
"codeName": "Bitfinex",
|
||||
"codeName": "bitfinex",
|
||||
"iconName": "bitfinex"
|
||||
},
|
||||
{
|
||||
"codeName": "Binance",
|
||||
"codeName": "binance",
|
||||
"iconName": "binance"
|
||||
},
|
||||
{
|
||||
"codeName": "Kucoin",
|
||||
"codeName": "kucoin",
|
||||
"iconName": "kucoin"
|
||||
},
|
||||
{
|
||||
"codeName": "Bittrex",
|
||||
"codeName": "bittrex",
|
||||
"iconName": "bittrex"
|
||||
},
|
||||
{
|
||||
"codeName": "Kraken",
|
||||
"codeName": "kraken",
|
||||
"iconName": "kraken"
|
||||
},
|
||||
{
|
||||
"codeName": "Poloniex",
|
||||
"codeName": "poloniex",
|
||||
"iconName": "poloniex"
|
||||
},
|
||||
{
|
||||
"codeName": "Upbit",
|
||||
"codeName": "upbit",
|
||||
"iconName": "upbit"
|
||||
},
|
||||
{
|
||||
"codeName": "Bitmex",
|
||||
"codeName": "bitmex",
|
||||
"iconName": "bitmex"
|
||||
},
|
||||
{
|
||||
"codeName": "Liquid",
|
||||
"codeName": "liquid",
|
||||
"iconName": "liquid"
|
||||
},
|
||||
{
|
||||
"codeName": "HitBTC",
|
||||
"codeName": "hitbtc",
|
||||
"iconName": "hitbtc"
|
||||
}
|
||||
]
|
||||
@@ -4613,12 +4675,28 @@
|
||||
{
|
||||
"type": "Exchange Assets",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Config Exchange Assets",
|
||||
"actionFunction": "uiObject.configEditor.activate",
|
||||
"label": "Config Exchange Assets",
|
||||
"iconPathOn": "html",
|
||||
"iconPathOff": "html"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Asset",
|
||||
"relatedUiObject": "Asset",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Add Missing Assets",
|
||||
"label": "Add Missing Assets",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Proceed",
|
||||
"workDoneLabel": "Done",
|
||||
"relatedUiObject": "Asset",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
@@ -4629,6 +4707,12 @@
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"editors": {
|
||||
"config": true
|
||||
},
|
||||
"initialValues": {
|
||||
"code": "{ \n\"addMissingAssets\": { \"quotedAsset\": \"USDT\"} \n}"
|
||||
},
|
||||
"addLeftIcons": true,
|
||||
"level": 3,
|
||||
"icon": "exchange-assets",
|
||||
@@ -4640,8 +4724,7 @@
|
||||
{
|
||||
"name": "assets",
|
||||
"type": "array",
|
||||
"childType": "Asset",
|
||||
"autoAdd": true
|
||||
"childType": "Asset"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -4749,12 +4832,28 @@
|
||||
{
|
||||
"type": "Exchange Markets",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Config Market",
|
||||
"actionFunction": "uiObject.configEditor.activate",
|
||||
"label": "Config Market",
|
||||
"iconPathOn": "html",
|
||||
"iconPathOff": "html"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Market",
|
||||
"relatedUiObject": "Market",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Add Missing Markets",
|
||||
"label": "Add Missing Markets",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Proceed",
|
||||
"workDoneLabel": "Request Sent",
|
||||
"relatedUiObject": "Market",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
@@ -4765,6 +4864,12 @@
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"editors": {
|
||||
"config": true
|
||||
},
|
||||
"initialValues": {
|
||||
"code": "{ \n\"codeName\": \"Write here the code name of the Market here.\"\n}"
|
||||
},
|
||||
"addLeftIcons": true,
|
||||
"level": 3,
|
||||
"icon": "exchange-markets",
|
||||
@@ -4776,14 +4881,20 @@
|
||||
{
|
||||
"name": "markets",
|
||||
"type": "array",
|
||||
"childType": "Market",
|
||||
"autoAdd": true
|
||||
"childType": "Market"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Market",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Config Market",
|
||||
"actionFunction": "uiObject.configEditor.activate",
|
||||
"label": "Config Market",
|
||||
"iconPathOn": "html",
|
||||
"iconPathOff": "html"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
@@ -4806,13 +4917,6 @@
|
||||
"relatedUiObject": "Super Action",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Config Market",
|
||||
"actionFunction": "uiObject.configEditor.activate",
|
||||
"label": "Config Market",
|
||||
"iconPathOn": "html",
|
||||
"iconPathOff": "html"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
@@ -4850,7 +4954,7 @@
|
||||
"config": true
|
||||
},
|
||||
"initialValues": {
|
||||
"code": "{ \n\"codeName\": \"Write here the name of the market as it is defined at the CCXT library.\"\n}"
|
||||
"code": "{ \n\"codeName\": \"Write here the name of the market.\"\n}"
|
||||
},
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Exchange Markets->"
|
||||
@@ -4975,8 +5079,7 @@
|
||||
{
|
||||
"name": "assets",
|
||||
"type": "array",
|
||||
"childType": "Exchange Account Asset",
|
||||
"autoAdd": true
|
||||
"childType": "Exchange Account Asset"
|
||||
}
|
||||
],
|
||||
"isPersonalData": true
|
||||
@@ -5151,6 +5254,7 @@
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"isTitleAllwaysVisible": true,
|
||||
"addLeftIcons": true,
|
||||
"level": 1,
|
||||
"icon": "dashboard",
|
||||
@@ -5623,7 +5727,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Data Mining",
|
||||
"type": "Exchange Tasks",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Run All Task Managers",
|
||||
@@ -5651,6 +5755,69 @@
|
||||
"relatedUiObject": "Task Manager",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Delete",
|
||||
"label": "Delete Exchange Tasks",
|
||||
"iconPathOn": "delete",
|
||||
"iconPathOff": "delete",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"addLeftIcons": true,
|
||||
"level": 2,
|
||||
"icon": "crypto-exchange",
|
||||
"referenceAttachesTo": {
|
||||
"compatibleTypes": "->Crypto Exchange->"
|
||||
},
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Data Mining->Testing Environmnet->Production Environmnet->Template Structure->"
|
||||
},
|
||||
"alternativeIcons": "Use Reference Parent",
|
||||
"title": [
|
||||
"Use Reference Parent"
|
||||
],
|
||||
"isTitleAllwaysVisible": true,
|
||||
"propertyNameAtParent": "exchangeTasks",
|
||||
"properties": [
|
||||
{
|
||||
"name": "taskManagers",
|
||||
"type": "array",
|
||||
"childType": "Task Manager",
|
||||
"monitorChildrenRunning": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Data Mining",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Run All Exchange Tasks",
|
||||
"label": "Run All Exchange Tasks",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Run",
|
||||
"workDoneLabel": "Run Request Sent",
|
||||
"iconPathOn": "paper-plane",
|
||||
"iconPathOff": "paper-plane",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Stop All Exchange Tasks",
|
||||
"label": "Stop All Exchange Tasks",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Stop",
|
||||
"workDoneLabel": "Stop Request Sent",
|
||||
"iconPathOn": "stop",
|
||||
"iconPathOff": "stop",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Exchange Tasks",
|
||||
"relatedUiObject": "Exchange Tasks",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
@@ -5670,9 +5837,9 @@
|
||||
"propertyNameAtParent": "dataMining",
|
||||
"properties": [
|
||||
{
|
||||
"name": "taskManagers",
|
||||
"name": "exchangeTasks",
|
||||
"type": "array",
|
||||
"childType": "Task Manager",
|
||||
"childType": "Exchange Tasks",
|
||||
"autoAdd": true,
|
||||
"monitorChildrenRunning": true
|
||||
}
|
||||
@@ -5681,10 +5848,30 @@
|
||||
{
|
||||
"type": "Testing Environment",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Run All Exchange Tasks",
|
||||
"label": "Run All Exchange Tasks",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Run",
|
||||
"workDoneLabel": "Run Request Sent",
|
||||
"iconPathOn": "paper-plane",
|
||||
"iconPathOff": "paper-plane",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Stop All Exchange Tasks",
|
||||
"label": "Stop All Exchange Tasks",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Stop",
|
||||
"workDoneLabel": "Stop Request Sent",
|
||||
"iconPathOn": "stop",
|
||||
"iconPathOff": "stop",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Task Manager",
|
||||
"relatedUiObject": "Task Manager",
|
||||
"label": "Add Exchange Tasks",
|
||||
"relatedUiObject": "Exchange Tasks",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
@@ -5710,16 +5897,43 @@
|
||||
"type": "array",
|
||||
"childType": "Task Manager",
|
||||
"autoAdd": true
|
||||
},
|
||||
{
|
||||
"name": "exchangeTasks",
|
||||
"type": "array",
|
||||
"childType": "Exchange Tasks",
|
||||
"autoAdd": true,
|
||||
"monitorChildrenRunning": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Production Environment",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Run All Exchange Tasks",
|
||||
"label": "Run All Exchange Tasks",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Run",
|
||||
"workDoneLabel": "Run Request Sent",
|
||||
"iconPathOn": "paper-plane",
|
||||
"iconPathOff": "paper-plane",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Stop All Exchange Tasks",
|
||||
"label": "Stop All Exchange Tasks",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Stop",
|
||||
"workDoneLabel": "Stop Request Sent",
|
||||
"iconPathOn": "stop",
|
||||
"iconPathOff": "stop",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Task Manager",
|
||||
"relatedUiObject": "Task Manager",
|
||||
"label": "Add Exchange Tasks",
|
||||
"relatedUiObject": "Exchange Tasks",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
@@ -5745,6 +5959,55 @@
|
||||
"type": "array",
|
||||
"childType": "Task Manager",
|
||||
"autoAdd": true
|
||||
},
|
||||
{
|
||||
"name": "exchangeTasks",
|
||||
"type": "array",
|
||||
"childType": "Exchange Tasks",
|
||||
"autoAdd": true,
|
||||
"monitorChildrenRunning": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Exchange Data Products",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Single Market Data",
|
||||
"relatedUiObject": "Single Market Data",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Delete",
|
||||
"label": "Delete Data Storage",
|
||||
"iconPathOn": "delete",
|
||||
"iconPathOff": "delete",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"alternativeIcons": "Use Reference Parent",
|
||||
"title": [
|
||||
"Use Reference Parent"
|
||||
],
|
||||
"isTitleAllwaysVisible": true,
|
||||
"addLeftIcons": true,
|
||||
"level": 3,
|
||||
"icon": "crypto-exchange",
|
||||
"referenceAttachesTo": {
|
||||
"compatibleTypes": "->Crypto Exchange->"
|
||||
},
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Session Independent Data->"
|
||||
},
|
||||
"propertyNameAtParent": "exchangeDataProducts",
|
||||
"properties": [
|
||||
{
|
||||
"name": "singleMarketData",
|
||||
"type": "array",
|
||||
"childType": "Single Market Data"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5753,8 +6016,8 @@
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Single Market Data",
|
||||
"relatedUiObject": "Single Market Data",
|
||||
"label": "Add Exchange",
|
||||
"relatedUiObject": "Exchange Data Products",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
@@ -5776,10 +6039,45 @@
|
||||
"propertyNameAtParent": "sessionIndependentData",
|
||||
"properties": [
|
||||
{
|
||||
"name": "singleMarketData",
|
||||
"name": "exchangeDataProducts",
|
||||
"type": "array",
|
||||
"childType": "Single Market Data",
|
||||
"autoAdd": true
|
||||
"childType": "Exchange Data Products"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Exchange Sessions",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Delete",
|
||||
"label": "Delete Exchange Sessions",
|
||||
"iconPathOn": "delete",
|
||||
"iconPathOff": "delete",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
}
|
||||
],
|
||||
"alternativeIcons": "Use Reference Parent",
|
||||
"title": [
|
||||
"Use Reference Parent"
|
||||
],
|
||||
"isTitleAllwaysVisible": true,
|
||||
"addLeftIcons": true,
|
||||
"level": 3,
|
||||
"icon": "crypto-exchange",
|
||||
"referenceAttachesTo": {
|
||||
"compatibleTypes": "->Crypto Exchange->"
|
||||
},
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Data Storage->"
|
||||
},
|
||||
"propertyNameAtParent": "exchangeSessions",
|
||||
"properties": [
|
||||
{
|
||||
"name": "sessionReferences",
|
||||
"type": "array",
|
||||
"childType": "Session Reference"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5788,8 +6086,8 @@
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Session Reference",
|
||||
"relatedUiObject": "Session Reference",
|
||||
"label": "Add Exchange Sessions",
|
||||
"relatedUiObject": "Exchange Sessions",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
@@ -5815,6 +6113,12 @@
|
||||
"type": "array",
|
||||
"childType": "Session Reference",
|
||||
"autoAdd": true
|
||||
},
|
||||
{
|
||||
"name": "exchangeSessions",
|
||||
"type": "array",
|
||||
"childType": "Exchange Sessions",
|
||||
"autoAdd": true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -5852,7 +6156,7 @@
|
||||
"compatibleTypes": "->Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->"
|
||||
},
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Session Based Data->Template Structure->"
|
||||
"compatibleTypes": "->Exchange Sessions->Template Structure->"
|
||||
},
|
||||
"propertyNameAtParent": "sessionReferences",
|
||||
"properties": [
|
||||
@@ -5895,7 +6199,7 @@
|
||||
"compatibleTypes": "->Market->"
|
||||
},
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Session Independent Data->Session Reference->Template Structure->"
|
||||
"compatibleTypes": "->Exchange Data Products->Session Reference->Template Structure->"
|
||||
},
|
||||
"propertyNameAtParent": "singleMarketData",
|
||||
"properties": [
|
||||
|
||||
@@ -61,11 +61,11 @@ function newAnimation () {
|
||||
try {
|
||||
if (window.canvasApp.visible === true) {
|
||||
/* We set the canvas to its normal width and height */
|
||||
browserCanvas.width = window.innerWidth
|
||||
browserCanvas.height = window.innerHeight - CURRENT_TOP_MARGIN
|
||||
// browserCanvas.width = window.innerWidth
|
||||
// browserCanvas.height = window.innerHeight - CURRENT_TOP_MARGIN
|
||||
|
||||
/* First thing is to clear the actual canvas */
|
||||
// clearBrowserCanvas()
|
||||
clearBrowserCanvas()
|
||||
|
||||
/* We loop through the callback functions collections and execute them all. */
|
||||
let performanceMap = new Map()
|
||||
@@ -139,6 +139,7 @@ function newAnimation () {
|
||||
}
|
||||
|
||||
/* Media Recording */
|
||||
videoRecorder.physics()
|
||||
if (areWeRecording === true) {
|
||||
videoRecorder.recordCanvas()
|
||||
}
|
||||
@@ -161,12 +162,7 @@ function newAnimation () {
|
||||
}
|
||||
|
||||
function clearBrowserCanvas () {
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
browserCanvasContext.rect(0, 0, browserCanvas.width, browserCanvas.height)
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.fill()
|
||||
browserCanvasContext.clearRect(0, 0, browserCanvas.width, browserCanvas.height)
|
||||
}
|
||||
}
|
||||
+34
-3
@@ -252,6 +252,28 @@ function newCanvas () {
|
||||
checkMediaRecording(event)
|
||||
canvas.chartingSpace.onKeyPressed(event)
|
||||
|
||||
if (event.key === 'Escape' && canvas.floatingSpace.inMapMode === true) {
|
||||
canvas.floatingSpace.exitMapMode()
|
||||
}
|
||||
|
||||
if (event.shiftKey === true && (event.ctrlKey === true || event.metaKey === true) && (event.key === 'M' || event.key === 'm')) {
|
||||
canvas.floatingSpace.toggleMapMode()
|
||||
event.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
if (event.shiftKey === true && (event.ctrlKey === true || event.metaKey === true) && (event.key === 'R' || event.key === 'r')) {
|
||||
canvas.floatingSpace.toggleDrawReferenceLines()
|
||||
event.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
if (event.shiftKey === true && (event.ctrlKey === true || event.metaKey === true) && (event.key === 'C' || event.key === 'c')) {
|
||||
canvas.floatingSpace.toggleDrawChainLines()
|
||||
event.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
let nodeOnFocus = canvas.designSpace.workspace.getNodeThatIsOnFocus()
|
||||
if (nodeOnFocus !== undefined) {
|
||||
if (nodeOnFocus.payload.uiObject.codeEditor !== undefined) {
|
||||
@@ -378,7 +400,7 @@ function newCanvas () {
|
||||
|
||||
if ((event.ctrlKey === true || event.metaKey === true) && event.altKey === true) {
|
||||
if ((event.keyCode >= 48 && event.keyCode <= 57) || (event.keyCode >= 65 && event.keyCode <= 90)) {
|
||||
/* From here we prevent the default behaviour */
|
||||
/* From here we prevent the default behaviour. Putting it earlier prevents imput box and text area to receive keystrokes */
|
||||
event.preventDefault()
|
||||
|
||||
let nodeUsingThisKey = canvas.designSpace.workspace.getNodeByShortcutKey(event.key)
|
||||
@@ -594,6 +616,12 @@ function newCanvas () {
|
||||
containerDragStarted = true
|
||||
floatingObjectDragStarted = true
|
||||
containerBeingDragged.eventHandler.raiseEvent('onDragStarted', point)
|
||||
|
||||
if (event.candelDragging === true) {
|
||||
containerBeingDragged = undefined
|
||||
containerDragStarted = false
|
||||
floatingObjectDragStarted = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -758,7 +786,7 @@ function newCanvas () {
|
||||
|
||||
let container
|
||||
|
||||
/* We check if the mouse is over an element of the Strategy Space / */
|
||||
/* We check if the mouse is over an element of the Designe Space / */
|
||||
if (thisObject.designSpace !== undefined) {
|
||||
container = thisObject.designSpace.getContainer(point)
|
||||
|
||||
@@ -842,6 +870,9 @@ function newCanvas () {
|
||||
// cross-browser wheel delta
|
||||
var event = window.event || event // old IE support
|
||||
event.delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail))
|
||||
if (IS_MAC) {
|
||||
event.delta = event.delta / MAC_AMOUNT_FACTOR
|
||||
}
|
||||
|
||||
/* We try first with panels. */
|
||||
|
||||
@@ -907,7 +938,7 @@ function newCanvas () {
|
||||
floatingObjectDragStarted ||
|
||||
viewPortBeingDragged
|
||||
) {
|
||||
ignoreNextClick = true
|
||||
ignoreNextClick = false
|
||||
}
|
||||
/* Turn off all the possible things that can be dragged. */
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ function newEdgeEditor () {
|
||||
fitFunction: undefined,
|
||||
isVisible: true,
|
||||
isMouseOver: undefined,
|
||||
resetAspectRatio: resetAspectRatio,
|
||||
onKeyPressed: onKeyPressed,
|
||||
physics: physics,
|
||||
drawForeground: drawForeground,
|
||||
@@ -28,6 +29,7 @@ function newEdgeEditor () {
|
||||
let whereIsMouseOver = 'outside'
|
||||
|
||||
let coordinateSystem
|
||||
let coordinateSystemWhenDragStarted
|
||||
|
||||
let onMouseOverEventSubscriptionId
|
||||
let onMouseNotOverEventSubscriptionId
|
||||
@@ -39,6 +41,25 @@ function newEdgeEditor () {
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
|
||||
mouseWhenDragStarted = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
|
||||
parentFrameWhenDragStarted = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
|
||||
let doubleClickCounter = 0
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
@@ -50,6 +71,16 @@ function newEdgeEditor () {
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
mouse = undefined
|
||||
mouseWhenDragStarted = undefined
|
||||
parentFrameWhenDragStarted = undefined
|
||||
|
||||
coordinateSystem = undefined
|
||||
|
||||
if (coordinateSystemWhenDragStarted !== undefined) {
|
||||
coordinateSystemWhenDragStarted.finalize()
|
||||
}
|
||||
|
||||
coordinateSystemWhenDragStarted = undefined
|
||||
}
|
||||
|
||||
function initialize (pCoordinateSystem) {
|
||||
@@ -74,7 +105,68 @@ function newEdgeEditor () {
|
||||
thisObject.isMouseOver = false
|
||||
}
|
||||
|
||||
function resetAspectRatio () {
|
||||
/* Resize the Time Machine to match the current screen aspect ration */
|
||||
|
||||
thisObject.container.parentContainer.frame.width = browserCanvas.width / TIME_MACHINE_WIDTH
|
||||
thisObject.container.parentContainer.frame.height = (browserCanvas.height - TOP_SPACE_HEIGHT - COCKPIT_SPACE_HEIGHT) / TIME_MACHINE_HEIGHT
|
||||
coordinateSystem.maxHeight = thisObject.container.parentContainer.frame.height
|
||||
coordinateSystem.maxWidth = thisObject.container.parentContainer.frame.width
|
||||
coordinateSystem.recalculateScale()
|
||||
thisObject.container.parentContainer.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
}
|
||||
|
||||
function onDoubleClick (event) {
|
||||
doubleClickCounter = 0
|
||||
if (canvas.chartingSpace.viewport.zoomLevel === DOUBLE_CLICK_ZOOM_OUT_LEVEL) {
|
||||
canvas.chartingSpace.viewport.displaceToContainer(thisObject.container.parentContainer)
|
||||
canvas.chartingSpace.viewport.zoomAtCenter(DOUBLE_CLICK_ZOOM_IN_LEVEL)
|
||||
return
|
||||
}
|
||||
if (canvas.chartingSpace.viewport.zoomLevel === DOUBLE_CLICK_ZOOM_IN_LEVEL) {
|
||||
canvas.chartingSpace.viewport.zoomAtCenter(DOUBLE_CLICK_ZOOM_IN_IN_LEVEL)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function onDragStarted (event) {
|
||||
if (doubleClickCounter > 0) {
|
||||
onDoubleClick(event)
|
||||
return
|
||||
} else {
|
||||
doubleClickCounter = 50
|
||||
}
|
||||
|
||||
mouseWhenDragStarted = {
|
||||
position: {
|
||||
x: event.x,
|
||||
y: event.y
|
||||
}
|
||||
}
|
||||
|
||||
parentFrameWhenDragStarted = {
|
||||
position: {
|
||||
x: thisObject.container.parentContainer.frame.position.x,
|
||||
y: thisObject.container.parentContainer.frame.position.y
|
||||
},
|
||||
width: thisObject.container.parentContainer.frame.width,
|
||||
height: thisObject.container.parentContainer.frame.height
|
||||
}
|
||||
|
||||
coordinateSystemWhenDragStarted = newCoordinateSystem()
|
||||
|
||||
let minValue = {
|
||||
x: coordinateSystem.min.x,
|
||||
y: coordinateSystem.min.y
|
||||
}
|
||||
|
||||
let maxValue = {
|
||||
x: coordinateSystem.max.x,
|
||||
y: coordinateSystem.max.y
|
||||
}
|
||||
|
||||
coordinateSystemWhenDragStarted.initialize(minValue, maxValue, coordinateSystem.maxWidth, coordinateSystem.maxHeight)
|
||||
|
||||
switch (event.buttons) {
|
||||
case 1: {
|
||||
whatHappened = 'left mouse button'
|
||||
@@ -104,6 +196,23 @@ function newEdgeEditor () {
|
||||
whatHappened = 'left or right arrow key pressed'
|
||||
return
|
||||
}
|
||||
|
||||
if (event.shiftKey === false && event.code === 'ArrowUp') {
|
||||
thisObject.container.frame.position.y = thisObject.container.frame.position.y + STEP
|
||||
whatHappened = 'up or down arrow key pressed'
|
||||
return
|
||||
}
|
||||
|
||||
if (event.shiftKey === false && event.code === 'ArrowDown') {
|
||||
thisObject.container.frame.position.y = thisObject.container.frame.position.y - STEP
|
||||
whatHappened = 'up or down arrow key pressed'
|
||||
return
|
||||
}
|
||||
|
||||
if (event.shiftKey === true && (event.ctrlKey === true || event.metaKey === true) && (event.key === 'A' || event.key === 'a')) {
|
||||
resetAspectRatio()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (event, purpose) {
|
||||
@@ -147,8 +256,28 @@ function newEdgeEditor () {
|
||||
}
|
||||
|
||||
function physics () {
|
||||
draggingPhysics()
|
||||
doubleClickPhysics()
|
||||
}
|
||||
|
||||
function doubleClickPhysics () {
|
||||
doubleClickCounter--
|
||||
if (doubleClickCounter < 0) {
|
||||
doubleClickCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
function draggingPhysics () {
|
||||
if (thisObject.container.frame.position.x === 0 && thisObject.container.frame.position.y === 0) { return }
|
||||
|
||||
let mouseNoZoom = canvas.chartingSpace.viewport.unTransformThisPoint(mouse.position)
|
||||
let mouseWhenDragStartedNoZoom = canvas.chartingSpace.viewport.unTransformThisPoint(mouseWhenDragStarted.position)
|
||||
|
||||
let dragVectorWhenDragStarted = {
|
||||
x: mouseNoZoom.x - mouseWhenDragStartedNoZoom.x,
|
||||
y: mouseNoZoom.y - mouseWhenDragStartedNoZoom.y
|
||||
}
|
||||
|
||||
let dragVector = {
|
||||
x: thisObject.container.frame.position.x,
|
||||
y: thisObject.container.frame.position.y
|
||||
@@ -157,28 +286,31 @@ function newEdgeEditor () {
|
||||
thisObject.container.frame.position.x = 0
|
||||
thisObject.container.frame.position.y = 0
|
||||
|
||||
const MIN_WIDTH = 100
|
||||
const MIN_HEIGHT = 50
|
||||
const MIN_WIDTH = 200
|
||||
const MIN_HEIGHT = 100
|
||||
|
||||
switch (whereIsMouseOver) {
|
||||
case 'center': {
|
||||
switch (whatHappened) {
|
||||
case 'left mouse button + SHIFT': {
|
||||
/* This is equivalent to drag the whole Time Machine, so we will apply the translation received onto the Time Machine container. */
|
||||
thisObject.container.parentContainer.frame.position.x = thisObject.container.parentContainer.frame.position.x + dragVector.x
|
||||
thisObject.container.parentContainer.frame.position.y = thisObject.container.parentContainer.frame.position.y + dragVector.y
|
||||
thisObject.container.parentContainer.frame.position.x = parentFrameWhenDragStarted.position.x + dragVectorWhenDragStarted.x
|
||||
thisObject.container.parentContainer.frame.position.y = parentFrameWhenDragStarted.position.y + dragVectorWhenDragStarted.y
|
||||
snapPointToGrid(thisObject.container.parentContainer.frame.position)
|
||||
thisObject.container.parentContainer.eventHandler.raiseEvent('onDisplace')
|
||||
break
|
||||
}
|
||||
case 'left mouse button': {
|
||||
let point = {
|
||||
x: -dragVector.x,
|
||||
y: -dragVector.y
|
||||
x: (-dragVectorWhenDragStarted.x),
|
||||
y: (-dragVectorWhenDragStarted.y)
|
||||
}
|
||||
let newMinDate = getDateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
let newMaxRate = getRateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
let xDifferenceMaxMin = coordinateSystem.max.x - coordinateSystem.min.x
|
||||
let yDifferenceMaxMin = coordinateSystem.max.y - coordinateSystem.min.y
|
||||
|
||||
let newMinDate = getDateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystemWhenDragStarted)
|
||||
let newMaxRate = getRateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystemWhenDragStarted)
|
||||
|
||||
let xDifferenceMaxMin = coordinateSystemWhenDragStarted.max.x - coordinateSystemWhenDragStarted.min.x
|
||||
let yDifferenceMaxMin = coordinateSystemWhenDragStarted.max.y - coordinateSystemWhenDragStarted.min.y
|
||||
coordinateSystem.min.x = newMinDate.valueOf()
|
||||
coordinateSystem.max.x = newMinDate.valueOf() + xDifferenceMaxMin
|
||||
coordinateSystem.min.y = newMaxRate - yDifferenceMaxMin
|
||||
@@ -189,11 +321,13 @@ function newEdgeEditor () {
|
||||
}
|
||||
coordinateSystem.recalculateScale(event)
|
||||
}
|
||||
break
|
||||
case 'left or right arrow key pressed': {
|
||||
let point = {
|
||||
x: -dragVector.x,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let newMinDate = getDateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
let xDifferenceMaxMin = coordinateSystem.max.x - coordinateSystem.min.x
|
||||
coordinateSystem.min.x = newMinDate.valueOf()
|
||||
@@ -204,23 +338,48 @@ function newEdgeEditor () {
|
||||
}
|
||||
coordinateSystem.recalculateScale(event)
|
||||
}
|
||||
break
|
||||
case 'up or down arrow key pressed': {
|
||||
let point = {
|
||||
x: 0,
|
||||
y: -dragVector.y
|
||||
}
|
||||
|
||||
let newMaxRate = getRateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
let yDifferenceMaxMin = coordinateSystem.max.y - coordinateSystem.min.y
|
||||
coordinateSystem.min.y = newMaxRate - yDifferenceMaxMin
|
||||
coordinateSystem.max.y = newMaxRate
|
||||
let event = {
|
||||
type: 'center dragged',
|
||||
dragVector: dragVector
|
||||
}
|
||||
coordinateSystem.recalculateScale(event)
|
||||
}
|
||||
break
|
||||
}
|
||||
thisObject.container.parentContainer.eventHandler.raiseEvent('onMouseOver', mouse.position)
|
||||
break
|
||||
}
|
||||
case 'top' : {
|
||||
if (thisObject.container.parentContainer.frame.height - dragVector.y < MIN_HEIGHT && dragVector.y > 0) {
|
||||
return
|
||||
dragVectorWhenDragStarted.x = 0
|
||||
|
||||
let newHight = parentFrameWhenDragStarted.height - dragVectorWhenDragStarted.y
|
||||
if (newHight < MIN_HEIGHT && dragVectorWhenDragStarted.y > 0) {
|
||||
dragVectorWhenDragStarted.y = parentFrameWhenDragStarted.height - MIN_HEIGHT
|
||||
}
|
||||
|
||||
thisObject.container.parentContainer.frame.position.y = parentFrameWhenDragStarted.position.y + dragVectorWhenDragStarted.y
|
||||
snapPointToGrid(thisObject.container.parentContainer.frame.position)
|
||||
thisObject.container.parentContainer.frame.height = parentFrameWhenDragStarted.height + (parentFrameWhenDragStarted.position.y - thisObject.container.parentContainer.frame.position.y)
|
||||
|
||||
let point = {
|
||||
x: dragVector.x,
|
||||
y: dragVector.y
|
||||
x: 0,
|
||||
y: (thisObject.container.parentContainer.frame.position.y - parentFrameWhenDragStarted.position.y)
|
||||
}
|
||||
let newMaxRate = getRateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
|
||||
thisObject.container.parentContainer.frame.position.y = thisObject.container.parentContainer.frame.position.y + dragVector.y
|
||||
thisObject.container.parentContainer.frame.height = thisObject.container.parentContainer.frame.height - dragVector.y
|
||||
/* This is equivalent to getRateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
|
||||
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.height)
|
||||
let newMaxRate = point.y
|
||||
|
||||
switch (whatHappened) {
|
||||
case 'left mouse button': {
|
||||
@@ -243,17 +402,25 @@ function newEdgeEditor () {
|
||||
break
|
||||
}
|
||||
case 'bottom' : {
|
||||
if (thisObject.container.parentContainer.frame.height + dragVector.y < MIN_HEIGHT && dragVector.y < 0) {
|
||||
return
|
||||
dragVectorWhenDragStarted.x = 0
|
||||
|
||||
let newHight = dragVectorWhenDragStarted.y + parentFrameWhenDragStarted.height
|
||||
if (newHight < MIN_HEIGHT && dragVectorWhenDragStarted.y < 0) {
|
||||
dragVectorWhenDragStarted.y = MIN_HEIGHT - parentFrameWhenDragStarted.height
|
||||
}
|
||||
|
||||
let point = {
|
||||
x: dragVector.x,
|
||||
y: dragVector.y + thisObject.container.frame.height
|
||||
x: 0,
|
||||
y: dragVectorWhenDragStarted.y + parentFrameWhenDragStarted.height + parentFrameWhenDragStarted.position.y
|
||||
}
|
||||
let newMinRate = getRateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
snapPointToGrid(point)
|
||||
point.y = point.y - parentFrameWhenDragStarted.position.y
|
||||
|
||||
thisObject.container.parentContainer.frame.height = thisObject.container.parentContainer.frame.height + dragVector.y
|
||||
thisObject.container.parentContainer.frame.height = point.y
|
||||
|
||||
/* This is equivalent to getRateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
|
||||
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.height)
|
||||
let newMinRate = point.y
|
||||
|
||||
switch (whatHappened) {
|
||||
case 'left mouse button': {
|
||||
@@ -276,17 +443,25 @@ function newEdgeEditor () {
|
||||
break
|
||||
}
|
||||
case 'left' : {
|
||||
if (thisObject.container.parentContainer.frame.width - dragVector.x < MIN_WIDTH && dragVector.x > 0) {
|
||||
return
|
||||
}
|
||||
let point = {
|
||||
x: dragVector.x,
|
||||
y: dragVector.y
|
||||
}
|
||||
let newMinDate = getDateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
dragVectorWhenDragStarted.y = 0
|
||||
|
||||
thisObject.container.parentContainer.frame.position.x = thisObject.container.parentContainer.frame.position.x + dragVector.x
|
||||
thisObject.container.parentContainer.frame.width = thisObject.container.parentContainer.frame.width - dragVector.x
|
||||
let newWidth = parentFrameWhenDragStarted.width - dragVectorWhenDragStarted.x
|
||||
if (newWidth < MIN_WIDTH && dragVectorWhenDragStarted.x > 0) {
|
||||
dragVectorWhenDragStarted.x = parentFrameWhenDragStarted.width - MIN_WIDTH
|
||||
}
|
||||
|
||||
thisObject.container.parentContainer.frame.position.x = parentFrameWhenDragStarted.position.x + dragVectorWhenDragStarted.x
|
||||
snapPointToGrid(thisObject.container.parentContainer.frame.position)
|
||||
thisObject.container.parentContainer.frame.width = parentFrameWhenDragStarted.width + (parentFrameWhenDragStarted.position.x - thisObject.container.parentContainer.frame.position.x)
|
||||
|
||||
let point = {
|
||||
x: (thisObject.container.parentContainer.frame.position.x - parentFrameWhenDragStarted.position.x),
|
||||
y: 0
|
||||
}
|
||||
|
||||
/* This is equivalent to getDateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
|
||||
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.width)
|
||||
let newMinDate = point.x
|
||||
|
||||
switch (whatHappened) {
|
||||
case 'left mouse button': {
|
||||
@@ -305,17 +480,25 @@ function newEdgeEditor () {
|
||||
break
|
||||
}
|
||||
case 'right' : {
|
||||
if (thisObject.container.parentContainer.frame.width + dragVector.x < MIN_WIDTH && dragVector.x < 0) {
|
||||
return
|
||||
dragVectorWhenDragStarted.y = 0
|
||||
|
||||
let newWidth = dragVectorWhenDragStarted.x + parentFrameWhenDragStarted.width
|
||||
if (newWidth < MIN_WIDTH && dragVectorWhenDragStarted.x < 0) {
|
||||
dragVectorWhenDragStarted.x = MIN_WIDTH - parentFrameWhenDragStarted.width
|
||||
}
|
||||
|
||||
let point = {
|
||||
x: dragVector.x + thisObject.container.frame.width,
|
||||
y: dragVector.y
|
||||
x: dragVectorWhenDragStarted.x + parentFrameWhenDragStarted.width + parentFrameWhenDragStarted.position.x,
|
||||
y: 0
|
||||
}
|
||||
let newMaxDate = getDateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
|
||||
snapPointToGrid(point)
|
||||
point.x = point.x - parentFrameWhenDragStarted.position.x
|
||||
|
||||
thisObject.container.parentContainer.frame.width = thisObject.container.parentContainer.frame.width + dragVector.x
|
||||
thisObject.container.parentContainer.frame.width = point.x
|
||||
|
||||
/* This is equivalent to getRateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
|
||||
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.width)
|
||||
let newMaxDate = point.x
|
||||
|
||||
switch (whatHappened) {
|
||||
case 'left mouse button': {
|
||||
@@ -334,6 +517,22 @@ function newEdgeEditor () {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function snapPointToGrid (point) {
|
||||
point.x = snapScalarToGrid(point.x)
|
||||
point.y = snapScalarToGrid(point.y)
|
||||
}
|
||||
|
||||
function snapScalarToGrid (scalar) {
|
||||
let sign
|
||||
if (scalar < 0) {
|
||||
sign = -1
|
||||
} else {
|
||||
sign = 1
|
||||
}
|
||||
const GRID_SIZE = 10
|
||||
return Math.trunc(scalar / GRID_SIZE) * GRID_SIZE + GRID_SIZE / 2 * sign
|
||||
}
|
||||
}
|
||||
|
||||
function drawForeground () {
|
||||
@@ -342,7 +541,7 @@ function newEdgeEditor () {
|
||||
let lineWidth
|
||||
|
||||
if (whereIsMouseOver === 'outside' || thisObject.isMouseOver === false) {
|
||||
edgeSize = EDGE_SIZE / 2
|
||||
edgeSize = 2
|
||||
lineWidth = 0.1
|
||||
} else {
|
||||
edgeSize = EDGE_SIZE
|
||||
|
||||
@@ -301,9 +301,16 @@ function newPlottersManager () {
|
||||
function draw () {
|
||||
if (thisObject.connectors === undefined) { return } // We need to wait
|
||||
/* First the Product Plotters. */
|
||||
let maxElementsPlotted = 0
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[thisObject.connectors.length - i - 1]
|
||||
connector.plotter.draw()
|
||||
let elementsPlotted = connector.plotter.draw()
|
||||
if (elementsPlotted !== undefined) {
|
||||
if (elementsPlotted > maxElementsPlotted) {
|
||||
maxElementsPlotted = elementsPlotted
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxElementsPlotted
|
||||
}
|
||||
}
|
||||
@@ -44,12 +44,14 @@ function newTimeMachine () {
|
||||
}
|
||||
}
|
||||
|
||||
let tabAnimation = 0
|
||||
let tabAnimationStatus = 'Close'
|
||||
let tabAnimationCounter = 0
|
||||
let wasOnFocus = false
|
||||
let drawScales = false
|
||||
let syncWithDesignerLoop = 0
|
||||
let timelineChartsMap = new Map()
|
||||
|
||||
let onViewportPositionChangedEventSuscriptionId
|
||||
let onViewportZoomChangedEventSuscriptionId
|
||||
let onMouseOverEventSuscriptionId
|
||||
let onMouseNotOverEventSuscriptionId
|
||||
let timeScaleMouseOverEventSuscriptionId
|
||||
@@ -69,13 +71,11 @@ function newTimeMachine () {
|
||||
thisObject.container.insideViewport = true
|
||||
thisObject.container.detectMouseOver = true
|
||||
|
||||
thisObject.container.frame.width = TIME_MACHINE_WIDTH
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT
|
||||
thisObject.container.frame.width = browserCanvas.width / TIME_MACHINE_WIDTH
|
||||
thisObject.container.frame.height = (browserCanvas.height - TOP_SPACE_HEIGHT - COCKPIT_SPACE_HEIGHT) / TIME_MACHINE_HEIGHT
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
canvas.chartingSpace.viewport.eventHandler.stopListening(onViewportPositionChangedEventSuscriptionId)
|
||||
canvas.chartingSpace.viewport.eventHandler.stopListening(onViewportZoomChangedEventSuscriptionId)
|
||||
timeMachineCoordinateSystem.eventHandler.stopListening(onScaleChangedEventSubscriptionId)
|
||||
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
@@ -148,8 +148,6 @@ function newTimeMachine () {
|
||||
|
||||
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
onViewportPositionChangedEventSuscriptionId = canvas.chartingSpace.viewport.eventHandler.listenToEvent('Position Changed', onViewportPositionChanged)
|
||||
onViewportZoomChangedEventSuscriptionId = canvas.chartingSpace.viewport.eventHandler.listenToEvent('Zoom Changed', onViewportZoomChanged)
|
||||
onScaleChangedEventSubscriptionId = timeMachineCoordinateSystem.eventHandler.listenToEvent('Scale Changed', onScaleChanged)
|
||||
|
||||
thisObject.edgeEditor = newEdgeEditor()
|
||||
@@ -314,36 +312,17 @@ function newTimeMachine () {
|
||||
}
|
||||
}
|
||||
|
||||
function onViewportZoomChanged (event) {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
recalculateCurrentDatetime()
|
||||
}
|
||||
}
|
||||
|
||||
function onViewportPositionChanged () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
recalculateCurrentDatetime()
|
||||
}
|
||||
}
|
||||
|
||||
function onScaleChanged () {
|
||||
recalculateCurrentDatetime()
|
||||
}
|
||||
|
||||
function recalculateCurrentDatetime () {
|
||||
/*
|
||||
The view port was moved or the view port zoom level was changed and the center of the screen points to a different datetime that we
|
||||
must calculate.
|
||||
*/
|
||||
let center = {
|
||||
x: (canvas.chartingSpace.viewport.visibleArea.bottomRight.x - canvas.chartingSpace.viewport.visibleArea.bottomLeft.x) / 2,
|
||||
y: (canvas.chartingSpace.viewport.visibleArea.bottomRight.y - canvas.chartingSpace.viewport.visibleArea.topRight.y) / 2
|
||||
x: thisObject.container.frame.width / 2,
|
||||
y: thisObject.container.frame.height / 2
|
||||
}
|
||||
|
||||
center = unTransformThisPoint(center, thisObject.container)
|
||||
center = timeMachineCoordinateSystem.unInverseTransform(center, thisObject.container.frame.height)
|
||||
|
||||
datetime = new Date(center.x)
|
||||
datetime = new Date(getDateFromPointAtContainer(center, thisObject.container, timeMachineCoordinateSystem))
|
||||
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[i]
|
||||
@@ -398,9 +377,38 @@ function newTimeMachine () {
|
||||
}
|
||||
panelPhysics()
|
||||
onFocusPhysics()
|
||||
tabAnimationPhysics()
|
||||
}
|
||||
|
||||
function tabAnimationPhysics () {
|
||||
const MAX_COUNTER_VALUE = 40
|
||||
const STEP = 10
|
||||
|
||||
if (wasOnFocus === true && thisObject.onFocus === false) {
|
||||
tabAnimationStatus = 'Closing'
|
||||
}
|
||||
if (wasOnFocus === false && thisObject.onFocus === true) {
|
||||
tabAnimationStatus = 'Opening'
|
||||
}
|
||||
|
||||
if (tabAnimationStatus === 'Closing') {
|
||||
tabAnimationCounter = tabAnimationCounter - STEP
|
||||
if (tabAnimationCounter <= 0) {
|
||||
tabAnimationCounter = 0
|
||||
tabAnimationStatus = 'Closed'
|
||||
}
|
||||
}
|
||||
if (tabAnimationStatus === 'Opening') {
|
||||
tabAnimationCounter = tabAnimationCounter + STEP
|
||||
if (tabAnimationCounter >= MAX_COUNTER_VALUE) {
|
||||
tabAnimationCounter = MAX_COUNTER_VALUE
|
||||
tabAnimationStatus = 'Open'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onFocusPhysics () {
|
||||
wasOnFocus = thisObject.onFocus
|
||||
if (thisObject.edgeEditor.isMouseOver === true) {
|
||||
thisObject.onFocus = true
|
||||
} else {
|
||||
@@ -409,7 +417,18 @@ function newTimeMachine () {
|
||||
}
|
||||
|
||||
function panelPhysics () {
|
||||
if (thisObject.container.frame.isCenterInViewPort() && canvas.chartingSpace.viewport.zoomTargetLevel > ZOOM_OUT_THRESHOLD_FOR_HIDDING_PANELS) {
|
||||
if (
|
||||
thisObject.container.frame.isInViewPort() &&
|
||||
canvas.chartingSpace.viewport.zoomLevel >= ZOOM_OUT_THRESHOLD_FOR_NOT_HIDDING_PANELS) {
|
||||
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Layers Panel')
|
||||
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Plotter Panel')
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
thisObject.container.frame.isCenterInViewPort() &&
|
||||
canvas.chartingSpace.viewport.zoomLevel >= ZOOM_OUT_THRESHOLD_FOR_HIDDING_PANELS
|
||||
) {
|
||||
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Layers Panel')
|
||||
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Plotter Panel')
|
||||
} else {
|
||||
@@ -529,9 +548,23 @@ function newTimeMachine () {
|
||||
function drawBackground () {
|
||||
drawChartsBackground()
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
if (drawScales === true) {
|
||||
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) { thisObject.timeScale.drawBackground() }
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawBackground() }
|
||||
}
|
||||
|
||||
let maxElementsPlotted = 0
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[thisObject.timelineCharts.length - i - 1]
|
||||
timelineChart.drawBackground()
|
||||
let elementsPlotted = timelineChart.drawBackground()
|
||||
if (elementsPlotted !== undefined) {
|
||||
if (elementsPlotted > maxElementsPlotted) {
|
||||
maxElementsPlotted = elementsPlotted
|
||||
}
|
||||
}
|
||||
}
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.adjustTimeFrame(maxElementsPlotted)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -619,13 +652,13 @@ function newTimeMachine () {
|
||||
if (description !== undefined) {
|
||||
label = description
|
||||
}
|
||||
printLabel(label, position.x + 15, position.y - 28, opacity, fontSize)
|
||||
printLabel(label, position.x + 20, position.y - 10, opacity, fontSize)
|
||||
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
browserCanvasContext.drawImage(
|
||||
icon, position.x - 0,
|
||||
position.y - 40,
|
||||
icon, position.x + 5,
|
||||
position.y - 22,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
@@ -653,52 +686,118 @@ function newTimeMachine () {
|
||||
}
|
||||
}
|
||||
|
||||
drawTab(0, 0, exchangeMarkets.size * tabAnimationCounter, 90, thisObject.container)
|
||||
|
||||
const INTER_EXCHANGE_SPACE = 60
|
||||
const INTER_MARKET_SPACE = 90
|
||||
const INTER_MARKET_SPACE = -100
|
||||
|
||||
exchangeMarkets.forEach((exchangeMarket, i) => {
|
||||
icon = exchangeMarket.exchangeIcon
|
||||
if (tabAnimationStatus === 'Open') {
|
||||
drawMarketNames()
|
||||
}
|
||||
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
browserCanvasContext.drawImage(
|
||||
icon, position.x - 0,
|
||||
position.y - 22,
|
||||
imageSize,
|
||||
imageSize)
|
||||
function drawMarketNames () {
|
||||
exchangeMarkets.forEach((exchangeMarket, i) => {
|
||||
browserCanvasContext.save()
|
||||
browserCanvasContext.translate(position.x, position.y)
|
||||
browserCanvasContext.rotate(-Math.PI / 2)
|
||||
|
||||
let xOffSet = -80
|
||||
|
||||
icon = exchangeMarket.exchangeIcon
|
||||
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
browserCanvasContext.drawImage(
|
||||
icon,
|
||||
-20 + xOffSet,
|
||||
-43,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
}
|
||||
|
||||
printLabel(exchangeMarket.exchangeName, -5 + xOffSet, -30, opacity, fontSize, UI_COLOR.GREY)
|
||||
|
||||
position.x = position.x + INTER_EXCHANGE_SPACE
|
||||
|
||||
icon = exchangeMarket.baseAssetIcon
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
browserCanvasContext.drawImage(
|
||||
icon,
|
||||
-20 + xOffSet,
|
||||
-22,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
}
|
||||
|
||||
printLabel(exchangeMarket.marketName, -5 + xOffSet, -10, opacity, fontSize, UI_COLOR.GREY)
|
||||
|
||||
icon = exchangeMarket.quotedAssetIcon
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
browserCanvasContext.drawImage(
|
||||
icon,
|
||||
+50 + xOffSet,
|
||||
-22,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
}
|
||||
|
||||
position.x = position.x + INTER_MARKET_SPACE
|
||||
|
||||
browserCanvasContext.restore()
|
||||
})
|
||||
}
|
||||
|
||||
function drawTab (x, y, width, height, container) {
|
||||
const GRADIENT = 0
|
||||
const X_OFFSET = -3
|
||||
const Y_OFFSET = 13
|
||||
const TAB_CORNERS_RADIUS = 5
|
||||
|
||||
let point = {
|
||||
x: x,
|
||||
y: y
|
||||
}
|
||||
point = transformThisPoint(point, container)
|
||||
|
||||
let point1 = {
|
||||
x: point.x + X_OFFSET,
|
||||
y: point.y + Y_OFFSET
|
||||
}
|
||||
|
||||
printLabel(exchangeMarket.exchangeName, position.x + 15, position.y - 10, opacity, fontSize)
|
||||
|
||||
position.x = position.x + INTER_EXCHANGE_SPACE
|
||||
|
||||
icon = exchangeMarket.baseAssetIcon
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
browserCanvasContext.drawImage(
|
||||
icon, position.x - 0,
|
||||
position.y - 22,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
let point2 = {
|
||||
x: point.x + X_OFFSET,
|
||||
y: point.y + height + Y_OFFSET
|
||||
}
|
||||
|
||||
printLabel(exchangeMarket.marketName, position.x + 15, position.y - 10, opacity, fontSize)
|
||||
|
||||
icon = exchangeMarket.quotedAssetIcon
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
browserCanvasContext.drawImage(
|
||||
icon, position.x + 70,
|
||||
position.y - 22,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
let point3 = {
|
||||
x: point.x - width + X_OFFSET,
|
||||
y: point.y + height - GRADIENT + Y_OFFSET
|
||||
}
|
||||
|
||||
position.x = position.x + INTER_MARKET_SPACE
|
||||
})
|
||||
let point4 = {
|
||||
x: point.x - width + X_OFFSET,
|
||||
y: point.y + GRADIENT + Y_OFFSET
|
||||
}
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y)
|
||||
browserCanvasContext.arc(point3.x, point3.y - TAB_CORNERS_RADIUS, TAB_CORNERS_RADIUS, 0.5 * Math.PI, 1.0 * Math.PI)
|
||||
// browserCanvasContext.lineTo(point4.x, point4.y)
|
||||
browserCanvasContext.arc(point4.x, point4.y + TAB_CORNERS_RADIUS, TAB_CORNERS_RADIUS, 1.0 * Math.PI, 1.5 * Math.PI)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ''
|
||||
browserCanvasContext.stroke()
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + opacity + ''
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
}
|
||||
|
||||
function recalculateCoordinateSystem () {
|
||||
@@ -720,4 +819,3 @@ function newTimeMachine () {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,9 +378,17 @@ function newTimelineChart () {
|
||||
|
||||
function drawBackground () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
if (drawScales === true) {
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawBackground() }
|
||||
}
|
||||
drawChartsBackground()
|
||||
if (thisObject.plotterManager !== undefined) {
|
||||
thisObject.plotterManager.draw()
|
||||
let elementsPlotted = thisObject.plotterManager.draw()
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.adjustTimeFrame(elementsPlotted)
|
||||
} else {
|
||||
return elementsPlotted
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ function newViewport () {
|
||||
mousePosition: undefined,
|
||||
margins: MARGINS,
|
||||
payload: undefined,
|
||||
zoomAtCenter: zoomAtCenter,
|
||||
changeZoom: changeZoom,
|
||||
onMouseWheel: onMouseWheel,
|
||||
transformThisPoint: transformThisPoint,
|
||||
@@ -39,6 +40,7 @@ function newViewport () {
|
||||
fitIntoVisibleArea: fitIntoVisibleArea,
|
||||
fitIntoViewport: fitIntoViewport,
|
||||
displace: displace,
|
||||
displaceToContainer: displaceToContainer,
|
||||
physics: physics,
|
||||
raiseEvents: raiseEvents,
|
||||
resize: resize,
|
||||
@@ -50,14 +52,7 @@ function newViewport () {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
let targetPosition = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
let positionIncrement = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.mousePosition = {
|
||||
x: 0,
|
||||
y: 0
|
||||
@@ -69,6 +64,8 @@ function newViewport () {
|
||||
thisObject.zoomTargetLevel = MIN_ZOOM_LEVEL
|
||||
INITIAL_TIME_PERIOD = recalculatePeriod(thisObject.zoomLevel)
|
||||
|
||||
let overrideMousePositionCounter = 0
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
@@ -137,8 +134,36 @@ function newViewport () {
|
||||
thisObject.eventHandler.raiseEvent('Position Changed', event)
|
||||
}
|
||||
|
||||
function displaceToContainer (container) {
|
||||
let targetPoint = {
|
||||
x: -container.frame.position.x - container.frame.width / 2,
|
||||
y: -container.frame.position.y - container.frame.height / 2
|
||||
}
|
||||
position.x = targetPoint.x + browserCanvas.width / 2
|
||||
position.y = targetPoint.y + (browserCanvas.height - COCKPIT_SPACE_HEIGHT - TOP_SPACE_HEIGHT) / 2 + TOP_SPACE_HEIGHT
|
||||
}
|
||||
|
||||
function zoomAtCenter (level) {
|
||||
thisObject.zoomTargetLevel = level
|
||||
overrideMousePositionCounter = 50
|
||||
ANIMATION_INCREMENT = 0.5
|
||||
}
|
||||
|
||||
function mousePositionPhysics () {
|
||||
if (overrideMousePositionCounter > 0) {
|
||||
thisObject.mousePosition.x = browserCanvas.width / 2
|
||||
thisObject.mousePosition.y = (browserCanvas.height - TOP_SPACE_HEIGHT - COCKPIT_SPACE_HEIGHT) / 2 + TOP_SPACE_HEIGHT
|
||||
|
||||
overrideMousePositionCounter--
|
||||
if (overrideMousePositionCounter < 0) {
|
||||
overrideMousePositionCounter = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (thisObject.visible === false) { return }
|
||||
mousePositionPhysics()
|
||||
animationPhysics()
|
||||
positioningPhysics()
|
||||
readObjectState()
|
||||
@@ -156,27 +181,19 @@ function newViewport () {
|
||||
function animationPhysics () {
|
||||
if (thisObject.zoomLevel < thisObject.zoomTargetLevel) {
|
||||
if (thisObject.zoomTargetLevel - thisObject.zoomLevel < ANIMATION_INCREMENT) {
|
||||
ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel)
|
||||
ANIMATION_INCREMENT = Math.round(Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) * 100) / 100
|
||||
}
|
||||
thisObject.zoomLevel = thisObject.zoomLevel + ANIMATION_INCREMENT
|
||||
thisObject.zoomLevel = Math.round((thisObject.zoomLevel + ANIMATION_INCREMENT) * 100) / 100
|
||||
changeZoom(thisObject.zoomLevel - ANIMATION_INCREMENT, thisObject.zoomLevel)
|
||||
}
|
||||
|
||||
if (thisObject.zoomLevel > thisObject.zoomTargetLevel) {
|
||||
if (thisObject.zoomLevel - thisObject.zoomTargetLevel < ANIMATION_INCREMENT) {
|
||||
ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel)
|
||||
ANIMATION_INCREMENT = Math.round(Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) * 100) / 100
|
||||
}
|
||||
thisObject.zoomLevel = thisObject.zoomLevel - ANIMATION_INCREMENT
|
||||
thisObject.zoomLevel = Math.round((thisObject.zoomLevel - ANIMATION_INCREMENT) * 100) / 100
|
||||
changeZoom(thisObject.zoomLevel + ANIMATION_INCREMENT, thisObject.zoomLevel)
|
||||
}
|
||||
|
||||
if (positionIncrement.y !== 0) {
|
||||
if (Math.trunc(Math.abs(targetPosition.y - position.y) * 1000) >= Math.trunc(Math.abs(positionIncrement.y) * 1000)) {
|
||||
position.y = position.y + positionIncrement.y
|
||||
} else {
|
||||
positionIncrement.y = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
@@ -186,8 +203,6 @@ function newViewport () {
|
||||
let amount = event.delta
|
||||
if (event.buttons === 4) { morePower = 2 } // Mouse wheel pressed.
|
||||
/* We adjust the sensitivity for Mac Users */
|
||||
let isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||
if (isMac) { amount = amount / 5 }
|
||||
|
||||
if (thisObject.zoomTargetLevel > 10) {
|
||||
amount = amount * 2
|
||||
@@ -205,9 +220,9 @@ function newViewport () {
|
||||
if (thisObject.zoomTargetLevel + amount * morePower < MIN_ZOOM_LEVEL) {
|
||||
return false
|
||||
}
|
||||
thisObject.zoomTargetLevel = thisObject.zoomTargetLevel + amount * morePower
|
||||
thisObject.zoomTargetLevel = Math.round((thisObject.zoomTargetLevel + amount * morePower) * MAC_AMOUNT_FACTOR) / MAC_AMOUNT_FACTOR
|
||||
|
||||
ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / ANIMATION_STEPS
|
||||
ANIMATION_INCREMENT = Math.round(Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / ANIMATION_STEPS * 100) / 100
|
||||
|
||||
let newEvent = {
|
||||
newLevel: thisObject.zoomTargetLevel,
|
||||
@@ -286,18 +301,8 @@ function newViewport () {
|
||||
position.x = position.x - newMouse.x + thisObject.mousePosition.x
|
||||
position.y = position.y - newMouse.y + thisObject.mousePosition.y
|
||||
|
||||
let testPoint = unTransformThisPoint(thisObject.mousePosition, newLevel)
|
||||
|
||||
saveObjectState()
|
||||
|
||||
targetPosition.x = position.x
|
||||
targetPosition.y = position.y
|
||||
|
||||
positionIncrement = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Zoom Changed')
|
||||
}
|
||||
|
||||
@@ -392,7 +397,7 @@ function newViewport () {
|
||||
}
|
||||
|
||||
function newZoomLevel (level) {
|
||||
thisObject.zoomLevel = level
|
||||
thisObject.zoomLevel = Math.round(level)
|
||||
thisObject.zoomTargetLevel = level
|
||||
INITIAL_TIME_PERIOD = recalculatePeriod(level)
|
||||
saveObjectState()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
function newQuotedAssetalances () {
|
||||
function newAssetalances () {
|
||||
const MODULE_NAME = 'Asset Balances'
|
||||
|
||||
let thisObject = {
|
||||
@@ -38,6 +38,9 @@ function newQuotedAssetalances () {
|
||||
let speedometer = newSpeedometer()
|
||||
|
||||
speedometer.initialize()
|
||||
speedometer.container.connectToParent(thisObject.container)
|
||||
speedometer.container.frame.position.x = thisObject.container.frame.width / 2
|
||||
speedometer.container.frame.position.y = thisObject.container.frame.height * (2 + i * 2) / 5
|
||||
thisObject.speedometers.push(speedometer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,12 +56,14 @@ function newSpeedometer () {
|
||||
const OPACITY = 1
|
||||
|
||||
let centerPoint = {
|
||||
x: thisObject.params.LEFT_OFFSET,
|
||||
y: COCKPIT_SPACE_POSITION - COCKPIT_SPACE_HEIGHT / 2 - 9
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
centerPoint = thisObject.container.frame.frameThisPoint(centerPoint)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIUS + RED_LINE_HIGHT, 0.85 * Math.PI, 2.15 * Math.PI)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIUS + RED_LINE_HIGHT, 0 * Math.PI, 2.0 * Math.PI)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + OPACITY + ')'
|
||||
@@ -196,8 +198,8 @@ function newSpeedometer () {
|
||||
if (isNaN(label) === false) {
|
||||
label = Number(label)
|
||||
|
||||
label = Math.trunc(label * Math.pow(10, thisObject.params.DECIMALS)) / Math.pow(10, thisObject.params.DECIMALS)
|
||||
if (label === 0) { label = label.toFixed(2) } else { label = label.toLocaleString() }
|
||||
label = dynamicDecimals(label, 2)
|
||||
if (label === 0) { label = label.toFixed(2) }
|
||||
}
|
||||
|
||||
// label = label.substring(0, 6)
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
function newCCXTFunctions () {
|
||||
thisObject = {
|
||||
addMissingExchanges: addMissingExchanges,
|
||||
addMissingAssets: addMissingAssets,
|
||||
addMissingMarkets: addMissingMarkets
|
||||
}
|
||||
|
||||
return thisObject
|
||||
|
||||
function addMissingExchanges (node, functionLibraryUiObjectsFromNodes) {
|
||||
currentExchanges = new Map()
|
||||
let parent = node.payload.parentNode
|
||||
if (parent !== undefined) {
|
||||
for (let i = 0; i < parent.cryptoExchanges.length; i++) {
|
||||
let cryptoExchanges = parent.cryptoExchanges[i]
|
||||
for (let j = 0; j < cryptoExchanges.exchanges.length; j++) {
|
||||
let exchange = cryptoExchanges.exchanges[j]
|
||||
let codeName = loadPropertyFromNodeConfig(exchange.payload, 'codeName')
|
||||
currentExchanges.set(codeName, exchange)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let params = {
|
||||
method: 'listExchanges',
|
||||
has: {
|
||||
fetchOHLCV: true,
|
||||
fetchMarkets: true
|
||||
}
|
||||
}
|
||||
|
||||
callServer(JSON.stringify(params), 'CCXT', onResponse)
|
||||
|
||||
function onResponse (err, data) {
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
node.payload.uiObject.setErrorMessage('Failed to Fetch Assets from the Exchange')
|
||||
return
|
||||
}
|
||||
|
||||
let exchanges = JSON.parse(data)
|
||||
for (let i = 0; i < exchanges.length; i++) {
|
||||
let exchange = exchanges[i]
|
||||
let existingExchange = currentExchanges.get(exchange.id)
|
||||
if (existingExchange === undefined) {
|
||||
let newExchange = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Crypto Exchange')
|
||||
newExchange.name = exchange.name
|
||||
newExchange.code = '{ \n\"codeName\": \"' + exchange.id + '\"\n}'
|
||||
newExchange.payload.floatingObject.collapseToggle()
|
||||
newExchange.exchangeAssets.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
|
||||
newExchange.exchangeMarkets.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
|
||||
newExchange.exchangeAccounts.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
|
||||
newExchange.exchangeAssets.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_050X
|
||||
newExchange.exchangeMarkets.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_100X
|
||||
newExchange.exchangeAccounts.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_025X
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addMissingAssets (node, functionLibraryUiObjectsFromNodes) {
|
||||
if (node.payload.parentNode === undefined) { return }
|
||||
|
||||
let currentAssets = new Map()
|
||||
for (let j = 0; j < node.assets.length; j++) {
|
||||
let asset = node.assets[j]
|
||||
let codeName = loadPropertyFromNodeConfig(asset.payload, 'codeName')
|
||||
currentAssets.set(codeName, asset)
|
||||
}
|
||||
|
||||
let exchangeId = loadPropertyFromNodeConfig(node.payload.parentNode.payload, 'codeName')
|
||||
|
||||
try {
|
||||
let params = {
|
||||
exchangeId: exchangeId,
|
||||
method: 'fetchMarkets'
|
||||
}
|
||||
callServer(JSON.stringify(params), 'CCXT', onResponse)
|
||||
|
||||
function onResponse (err, data) {
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
node.payload.uiObject.setErrorMessage('Failed to Fetch Assets from the Exchange')
|
||||
return
|
||||
}
|
||||
let queryParams = loadPropertyFromNodeConfig(node.payload, 'addMissingAssets')
|
||||
|
||||
let markets = JSON.parse(data)
|
||||
for (let i = 0; i < markets.length; i++) {
|
||||
let market = markets[i]
|
||||
|
||||
if (queryParams !== undefined) {
|
||||
if (queryParams.baseAsset !== undefined) {
|
||||
if (market.base.indexOf(queryParams.baseAsset) >= 0) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (queryParams.quotedAsset !== undefined) {
|
||||
if (market.quote.indexOf(queryParams.quotedAsset) >= 0) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentAssets.get(market.base) === undefined) {
|
||||
addAsset(market.base)
|
||||
currentAssets.set(market.base, market.base)
|
||||
}
|
||||
if (currentAssets.get(market.quote) === undefined) {
|
||||
addAsset(market.quote)
|
||||
currentAssets.set(market.quote, market.quote)
|
||||
}
|
||||
|
||||
function addAsset (name) {
|
||||
let newAsseet = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Asset')
|
||||
newAsseet.name = name
|
||||
newAsseet.code = '{ \n\"codeName\": \"' + name + '\"\n}'
|
||||
newAsseet.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_360
|
||||
newAsseet.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_200X
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
node.payload.uiObject.setErrorMessage('Failed to Fetch Assets from the Exchange')
|
||||
console.log(err.stack)
|
||||
}
|
||||
}
|
||||
|
||||
function addMissingMarkets (node, functionLibraryUiObjectsFromNodes, functionLibraryNodeCloning) {
|
||||
if (node.payload.parentNode === undefined) { return }
|
||||
if (node.payload.parentNode.exchangeAssets === undefined) { return }
|
||||
if (node.payload.parentNode.payload.parentNode === undefined) { return }
|
||||
if (node.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { return }
|
||||
if (node.payload.parentNode.payload.parentNode.payload.parentNode.superActions === undefined) { return }
|
||||
|
||||
let currentAssets = new Map()
|
||||
let exchangeAssets = node.payload.parentNode.exchangeAssets
|
||||
for (let j = 0; j < exchangeAssets.assets.length; j++) {
|
||||
let asset = exchangeAssets.assets[j]
|
||||
let codeName = loadPropertyFromNodeConfig(asset.payload, 'codeName')
|
||||
currentAssets.set(codeName, asset)
|
||||
}
|
||||
|
||||
let currentMarkets = new Map()
|
||||
let exchangeMarkets = node
|
||||
for (let j = 0; j < exchangeMarkets.markets.length; j++) {
|
||||
let asset = exchangeMarkets.markets[j]
|
||||
let codeName = loadPropertyFromNodeConfig(asset.payload, 'codeName')
|
||||
currentMarkets.set(codeName, asset)
|
||||
}
|
||||
|
||||
let exchangeId = loadPropertyFromNodeConfig(node.payload.parentNode.payload, 'codeName')
|
||||
|
||||
try {
|
||||
let params = {
|
||||
exchangeId: exchangeId,
|
||||
method: 'fetchMarkets'
|
||||
}
|
||||
callServer(JSON.stringify(params), 'CCXT', onResponse)
|
||||
|
||||
function onResponse (err, data) {
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
node.payload.uiObject.setErrorMessage('Failed to Fetch Assets from the Exchange')
|
||||
return
|
||||
}
|
||||
|
||||
let markets = JSON.parse(data)
|
||||
for (let i = 0; i < markets.length; i++) {
|
||||
let market = markets[i]
|
||||
let baseAsset = currentAssets.get(market.base)
|
||||
let quotedAsset = currentAssets.get(market.quote)
|
||||
|
||||
if (baseAsset === undefined) {
|
||||
continue
|
||||
}
|
||||
if (quotedAsset === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (currentMarkets.get(market.symbol) === undefined) {
|
||||
addMarket(market.symbol, baseAsset, quotedAsset)
|
||||
}
|
||||
|
||||
function addMarket (name, baseAsset, quotedAsset) {
|
||||
let newMarket = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Market')
|
||||
newMarket.name = name
|
||||
newMarket.code = '{ \n\"codeName\": \"' + name + '\"\n}'
|
||||
newMarket.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
|
||||
newMarket.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_050X
|
||||
newMarket.baseAsset.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_45
|
||||
newMarket.quotedAsset.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_45
|
||||
newMarket.baseAsset.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_100X
|
||||
newMarket.quotedAsset.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_150X
|
||||
newMarket.baseAsset.payload.referenceParent = baseAsset
|
||||
newMarket.quotedAsset.payload.referenceParent = quotedAsset
|
||||
|
||||
let superActions = node.payload.parentNode.payload.parentNode.payload.parentNode.superActions
|
||||
|
||||
for (let j = 0; j < superActions.superActions.length; j++) {
|
||||
let superAction = superActions.superActions[j]
|
||||
let clone = functionLibraryNodeCloning.getNodeClone(superAction)
|
||||
functionLibraryUiObjectsFromNodes.createUiObjectFromNode(clone, newMarket, newMarket)
|
||||
newMarket.superActions.push(clone)
|
||||
switch (j) {
|
||||
case 0:
|
||||
clone.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_025X
|
||||
break
|
||||
case 1:
|
||||
clone.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_050X
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
node.payload.uiObject.setErrorMessage('Failed to Fetch Assets from the Exchange')
|
||||
console.log(err.stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ function newSessionFunctions () {
|
||||
let lightingPath = '' +
|
||||
'Trading System->' +
|
||||
'Parameters->' +
|
||||
'Base Asset->Time Range->Time Frame->Slippage->Fee Structure->' +
|
||||
'Base Asset->Quoted Asset->Time Range->Time Frame->Slippage->Fee Structure->' +
|
||||
'Exchange Account Asset->Asset->' +
|
||||
'Strategy->' +
|
||||
'Trigger Stage->Trigger On Event->Trigger Off Event->Take Position Event->' +
|
||||
@@ -53,7 +53,7 @@ function newSessionFunctions () {
|
||||
lightingPath = '' +
|
||||
'Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' +
|
||||
'Parameters->' +
|
||||
'Base Asset->Time Range->Time Frame->Slippage->Fee Structure->' +
|
||||
'Base Asset->Quoted Asset->Time Range->Time Frame->Slippage->Fee Structure->' +
|
||||
'Exchange Account Asset->Asset->'
|
||||
|
||||
let session = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
|
||||
|
||||
@@ -9,12 +9,42 @@ function newSuperScriptsFunctions () {
|
||||
try {
|
||||
let clone = functionLibraryNodeCloning.getNodeClone
|
||||
let executionResult = true
|
||||
let superAction = node
|
||||
|
||||
function setup (templateClone, target) {
|
||||
function setup (templateClone, target, exchange, exchangeNodeType, arrayPropertyName) {
|
||||
spawnPosition.x = target.payload.position.x
|
||||
spawnPosition.y = target.payload.position.y
|
||||
|
||||
functionLibraryUiObjectsFromNodes.createUiObjectFromNode(templateClone, target, target)
|
||||
if (exchange === undefined) {
|
||||
functionLibraryUiObjectsFromNodes.createUiObjectFromNode(templateClone, target, target)
|
||||
} else {
|
||||
let definition = APP_SCHEMA_MAP.get(target.type)
|
||||
for (let i = 0; i < definition.properties.length; i++) {
|
||||
let property = definition.properties[i]
|
||||
if (property.childType === exchangeNodeType) {
|
||||
let exchanges = target[property.name]
|
||||
if (exchanges === undefined) {
|
||||
exchanges = []
|
||||
}
|
||||
let targetExchange
|
||||
for (let j = 0; j < exchanges.length; j++) {
|
||||
let thisExchange = exchanges[j]
|
||||
if (thisExchange.payload.referenceParent !== undefined) {
|
||||
if (thisExchange.payload.referenceParent.id === exchange.id) {
|
||||
targetExchange = thisExchange
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetExchange === undefined) {
|
||||
targetExchange = functionLibraryUiObjectsFromNodes.addUIObject(target, exchangeNodeType)
|
||||
targetExchange.payload.referenceParent = exchange
|
||||
}
|
||||
let nodesArray = targetExchange[arrayPropertyName]
|
||||
nodesArray.push(templateClone)
|
||||
functionLibraryUiObjectsFromNodes.createUiObjectFromNode(templateClone, targetExchange, targetExchange)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function deleteNode (node) {
|
||||
@@ -35,7 +65,6 @@ function newSuperScriptsFunctions () {
|
||||
executionResult = false
|
||||
}
|
||||
|
||||
let superAction = node
|
||||
let masterScript = node.payload.referenceParent
|
||||
|
||||
eval(masterScript.javascriptCode.code)
|
||||
|
||||
@@ -5,7 +5,9 @@ function newTaskFunctions () {
|
||||
runAllTasks: runAllTasks,
|
||||
stopAllTasks: stopAllTasks,
|
||||
runAllTaskManagers: runAllTaskManagers,
|
||||
stopAllTaskManagers: stopAllTaskManagers
|
||||
stopAllTaskManagers: stopAllTaskManagers,
|
||||
runAllExchangeTasks: runAllExchangeTasks,
|
||||
stopAllExchangeTasks: stopAllExchangeTasks
|
||||
}
|
||||
|
||||
return thisObject
|
||||
@@ -79,9 +81,9 @@ function newTaskFunctions () {
|
||||
taskId: node.id,
|
||||
taskName: node.name
|
||||
}
|
||||
systemEventHandler.raiseEvent('Task Manager', 'Stop Task', event)
|
||||
|
||||
node.payload.uiObject.stop(callBackFunction)
|
||||
systemEventHandler.raiseEvent('Task Manager', 'Stop Task', event)
|
||||
|
||||
if (node.bot === undefined) { return }
|
||||
if (node.bot.processes.length === 0) { return }
|
||||
@@ -110,9 +112,9 @@ function newTaskFunctions () {
|
||||
}
|
||||
}
|
||||
|
||||
function runAllTaskManagers (dataMining, functionLibraryProtocolNode) {
|
||||
for (let i = 0; i < dataMining.taskManagers.length; i++) {
|
||||
let node = dataMining.taskManagers[i]
|
||||
function runAllTaskManagers (parent, functionLibraryProtocolNode) {
|
||||
for (let i = 0; i < parent.taskManagers.length; i++) {
|
||||
let node = parent.taskManagers[i]
|
||||
let menu = node.payload.uiObject.menu
|
||||
|
||||
menu.internalClick('Run All Tasks')
|
||||
@@ -120,13 +122,32 @@ function newTaskFunctions () {
|
||||
}
|
||||
}
|
||||
|
||||
function stopAllTaskManagers (dataMining, functionLibraryProtocolNode) {
|
||||
for (let i = 0; i < dataMining.taskManagers.length; i++) {
|
||||
let node = dataMining.taskManagers[i]
|
||||
function stopAllTaskManagers (parent, functionLibraryProtocolNode) {
|
||||
for (let i = 0; i < parent.taskManagers.length; i++) {
|
||||
let node = parent.taskManagers[i]
|
||||
let menu = node.payload.uiObject.menu
|
||||
|
||||
menu.internalClick('Stop All Tasks')
|
||||
menu.internalClick('Stop All Tasks')
|
||||
}
|
||||
}
|
||||
function runAllExchangeTasks (parent, functionLibraryProtocolNode) {
|
||||
for (let i = 0; i < parent.exchangeTasks.length; i++) {
|
||||
let node = parent.exchangeTasks[i]
|
||||
let menu = node.payload.uiObject.menu
|
||||
|
||||
menu.internalClick('Run All Task Managers')
|
||||
menu.internalClick('Run All Task Managers')
|
||||
}
|
||||
}
|
||||
|
||||
function stopAllExchangeTasks (parent, functionLibraryProtocolNode) {
|
||||
for (let i = 0; i < parent.exchangeTasks.length; i++) {
|
||||
let node = parent.exchangeTasks[i]
|
||||
let menu = node.payload.uiObject.menu
|
||||
|
||||
menu.internalClick('Stop All Task Managers')
|
||||
menu.internalClick('Stop All Task Managers')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,112 +159,92 @@ function newUiObjectsFromNodes () {
|
||||
}
|
||||
|
||||
let parentNodeDefinition = APP_SCHEMA_MAP.get(parentNode.type)
|
||||
if (parentNodeDefinition !== undefined) {
|
||||
if (parentNodeDefinition === undefined) {
|
||||
console.log('Cannot addUIOBject from parent of ' + type + ' because that type it is not defined at the APP_SCHEMA.')
|
||||
}
|
||||
/* Resolve Initial Values */
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(object.type)
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(object.type)
|
||||
|
||||
if (nodeDefinition.isHierarchyHead === true) {
|
||||
parentNode.rootNodes.push(object)
|
||||
createUiObject(true, object.type, object.name, object, parentNode, undefined)
|
||||
return object
|
||||
if (nodeDefinition === undefined) {
|
||||
console.log('Cannot addUIOBject of ' + type + ' because that type it is not defined at the APP_SCHEMA.')
|
||||
}
|
||||
|
||||
if (nodeDefinition.initialValues !== undefined) {
|
||||
if (nodeDefinition.initialValues.code !== undefined) {
|
||||
object.code = nodeDefinition.initialValues.code
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeDefinition.isHierarchyHead === true) {
|
||||
parentNode.rootNodes.push(object)
|
||||
createUiObject(true, object.type, object.name, object, parentNode, undefined)
|
||||
return object
|
||||
}
|
||||
|
||||
/* For the cases where an node is not chained to its parent but to the one at the parent before it at its collection */
|
||||
let chainParent = parentNode
|
||||
if (nodeDefinition.chainedToSameType === true) {
|
||||
if (parentNodeDefinition.properties !== undefined) {
|
||||
for (let i = 0; i < parentNodeDefinition.properties.length; i++) {
|
||||
let property = parentNodeDefinition.properties[i]
|
||||
if (property.childType === type) {
|
||||
if (property.type === 'array') {
|
||||
if (parentNode[property.name] !== undefined) {
|
||||
if (parentNode[property.name].length > 0) {
|
||||
let nodeChildren = parentNode[property.name]
|
||||
chainParent = nodeChildren[nodeChildren.length - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create Empty Arrays for properties of type Array */
|
||||
if (nodeDefinition.properties !== undefined) {
|
||||
for (let i = 0; i < nodeDefinition.properties.length; i++) {
|
||||
let property = nodeDefinition.properties[i]
|
||||
if (property.type === 'array') {
|
||||
object[property.name] = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.initialValues !== undefined) {
|
||||
if (nodeDefinition.initialValues.code !== undefined) {
|
||||
object.code = nodeDefinition.initialValues.code
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect to Parent */
|
||||
let chainParent = parentNode
|
||||
if (nodeDefinition.chainedToSameType === true) {
|
||||
if (parentNodeDefinition.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 < parentNodeDefinition.properties.length; i++) {
|
||||
let property = parentNodeDefinition.properties[i]
|
||||
if (property.childType === type) {
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
if (property.name !== previousPropertyName) {
|
||||
parentNode[property.name] = object
|
||||
previousPropertyName = property.name
|
||||
if (property.type === 'array') {
|
||||
if (parentNode[property.name] !== undefined) {
|
||||
if (parentNode[property.name].length > 0) {
|
||||
let nodeChildren = parentNode[property.name]
|
||||
chainParent = nodeChildren[nodeChildren.length - 1]
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'array': {
|
||||
if (parentNode[property.name] === undefined) {
|
||||
parentNode[property.name] = []
|
||||
}
|
||||
if (property.maxItems !== undefined) {
|
||||
if (parentNode[property.name].length < property.maxItems) {
|
||||
parentNode[property.name].push(object)
|
||||
} else {
|
||||
return // Object can not be created.
|
||||
}
|
||||
} else {
|
||||
parentNode[property.name].push(object)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createUiObject(true, object.type, object.name, object, parentNode, chainParent)
|
||||
/* Create Empty Arrays for properties of type Array */
|
||||
if (nodeDefinition.properties !== undefined) {
|
||||
for (let i = 0; i < nodeDefinition.properties.length; i++) {
|
||||
let property = nodeDefinition.properties[i]
|
||||
if (property.type === 'array') {
|
||||
object[property.name] = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Auto Add more Children */
|
||||
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]
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.initialValues !== undefined) {
|
||||
if (nodeDefinition.initialValues.code !== undefined) {
|
||||
object.code = nodeDefinition.initialValues.code
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect to Parent */
|
||||
if (parentNodeDefinition.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 < parentNodeDefinition.properties.length; i++) {
|
||||
let property = parentNodeDefinition.properties[i]
|
||||
if (property.childType === type) {
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
if (property.name !== previousPropertyName) {
|
||||
if (property.autoAdd === true) {
|
||||
addUIObject(object, property.childType)
|
||||
previousPropertyName = property.name
|
||||
}
|
||||
parentNode[property.name] = object
|
||||
previousPropertyName = property.name
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'array': {
|
||||
if (property.autoAdd === true) {
|
||||
if (object[property.name] === undefined) {
|
||||
object[property.name] = []
|
||||
if (parentNode[property.name] === undefined) {
|
||||
parentNode[property.name] = []
|
||||
}
|
||||
if (property.maxItems !== undefined) {
|
||||
if (parentNode[property.name].length < property.maxItems) {
|
||||
parentNode[property.name].push(object)
|
||||
} else {
|
||||
return // Object can not be created.
|
||||
}
|
||||
addUIObject(object, property.childType)
|
||||
} else {
|
||||
parentNode[property.name].push(object)
|
||||
}
|
||||
}
|
||||
break
|
||||
@@ -272,6 +252,38 @@ function newUiObjectsFromNodes () {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createUiObject(true, object.type, object.name, object, parentNode, chainParent)
|
||||
|
||||
/* Auto Add more Children */
|
||||
if (nodeDefinition.properties !== undefined) {
|
||||
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
|
||||
for (let i = 0; i < nodeDefinition.properties.length; i++) {
|
||||
let property = nodeDefinition.properties[i]
|
||||
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
if (property.name !== previousPropertyName) {
|
||||
if (property.autoAdd === true) {
|
||||
addUIObject(object, property.childType)
|
||||
previousPropertyName = property.name
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'array': {
|
||||
if (property.autoAdd === true) {
|
||||
if (object[property.name] === undefined) {
|
||||
object[property.name] = []
|
||||
}
|
||||
addUIObject(object, property.childType)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
@@ -399,6 +411,27 @@ function newUiObjectsFromNodes () {
|
||||
node.payload = payload
|
||||
node.type = uiObjectType
|
||||
|
||||
/*
|
||||
Now we copy the possible frame saved to the payload where it can be used. A saved frame stores the position of a a chartingSpace object related to a node.
|
||||
This will prevent that if those charting space objects never get activated, that the frame information is lost when the workspace is saved.
|
||||
*/
|
||||
if (node.savedPayload !== undefined) {
|
||||
if (node.savedPayload.frame !== undefined) {
|
||||
let frame = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
frame.position.x = node.savedPayload.frame.position.x
|
||||
frame.position.y = node.savedPayload.frame.position.y
|
||||
frame.width = node.savedPayload.frame.width
|
||||
frame.height = node.savedPayload.frame.height
|
||||
frame.radius = node.savedPayload.frame.radius
|
||||
saveFrame(payload, frame)
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we mount the floating object where the UIOBject will be laying on top of */
|
||||
canvas.floatingSpace.uiObjectConstructor.createUiObject(userAddingNew, payload)
|
||||
|
||||
@@ -407,7 +440,9 @@ function newUiObjectsFromNodes () {
|
||||
/* Check if there are tasks to run */
|
||||
if (userAddingNew === false && uiObjectType === 'Task' && node.savedPayload !== undefined) {
|
||||
if (node.savedPayload.uiObject.isRunning === true) {
|
||||
tasksToRun.push(node)
|
||||
if (node.payload.parentNode !== undefined) {
|
||||
tasksToRun.push(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +450,9 @@ function newUiObjectsFromNodes () {
|
||||
if (userAddingNew === false && node.savedPayload !== undefined) {
|
||||
if (uiObjectType === 'Live Trading Session' || uiObjectType === 'Fordward Testing Session' || uiObjectType === 'Backtesting Session' || uiObjectType === 'Paper Trading Session') {
|
||||
if (node.savedPayload.uiObject.isRunning === true) {
|
||||
sessionsToRun.push(node)
|
||||
if (node.payload.parentNode !== undefined) {
|
||||
sessionsToRun.push(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ function newWorkspace () {
|
||||
container: undefined,
|
||||
enabled: false,
|
||||
nodeChildren: undefined,
|
||||
getHierarchyHeads: getHierarchyHeads,
|
||||
getNodeThatIsOnFocus: getNodeThatIsOnFocus,
|
||||
getNodeByShortcutKey: getNodeByShortcutKey,
|
||||
stopAllRunningTasks: stopAllRunningTasks,
|
||||
@@ -57,6 +58,7 @@ function newWorkspace () {
|
||||
let functionLibraryShortcutKeys = newShortcutKeys()
|
||||
let functionLibraryOnFocus = newOnFocus()
|
||||
let functionLibrarySuperScripts = newSuperScriptsFunctions()
|
||||
let functionLibraryCCXTFunctions = newCCXTFunctions()
|
||||
|
||||
thisObject.nodeChildren = newNodeChildren()
|
||||
|
||||
@@ -88,7 +90,7 @@ function newWorkspace () {
|
||||
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode)
|
||||
thisObject.enabled = true
|
||||
|
||||
setInterval(saveWorkspace, 30000)
|
||||
setInterval(saveWorkspace, 10000)
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
|
||||
}
|
||||
@@ -183,22 +185,16 @@ function newWorkspace () {
|
||||
for (let j = 0; j < rootNode.networkNodes.length; j++) {
|
||||
let networkNode = rootNode.networkNodes[j]
|
||||
if (networkNode.dataMining !== undefined) {
|
||||
for (let i = 0; i < networkNode.dataMining.taskManagers.length; i++) {
|
||||
let taskManager = networkNode.dataMining.taskManagers[i]
|
||||
taskManager.payload.uiObject.menu.internalClick('Stop All Tasks')
|
||||
}
|
||||
networkNode.dataMining.payload.uiObject.menu.internalClick('Stop All Exchange Tasks')
|
||||
networkNode.dataMining.payload.uiObject.menu.internalClick('Stop All Exchange Tasks')
|
||||
}
|
||||
if (networkNode.testingEnvironment !== undefined) {
|
||||
for (let i = 0; i < networkNode.testingEnvironment.taskManagers.length; i++) {
|
||||
let taskManager = networkNode.testingEnvironment.taskManagers[i]
|
||||
taskManager.payload.uiObject.menu.internalClick('Stop All Tasks')
|
||||
}
|
||||
networkNode.testingEnvironment.payload.uiObject.menu.internalClick('Stop All Exchange Tasks')
|
||||
networkNode.testingEnvironment.payload.uiObject.menu.internalClick('Stop All Exchange Tasks')
|
||||
}
|
||||
if (networkNode.productionEnvironment !== undefined) {
|
||||
for (let i = 0; i < networkNode.productionEnvironment.taskManagers.length; i++) {
|
||||
let taskManager = networkNode.productionEnvironment.taskManagers[i]
|
||||
taskManager.payload.uiObject.menu.internalClick('Stop All Tasks')
|
||||
}
|
||||
networkNode.productionEnvironment.payload.uiObject.menu.internalClick('Stop All Exchange Tasks')
|
||||
networkNode.productionEnvironment.payload.uiObject.menu.internalClick('Stop All Exchange Tasks')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,6 +218,20 @@ function newWorkspace () {
|
||||
}
|
||||
}
|
||||
|
||||
function getHierarchyHeads () {
|
||||
let nodes = []
|
||||
for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) {
|
||||
let rootNode = thisObject.workspaceNode.rootNodes[i]
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(rootNode.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isHierarchyHead === true) {
|
||||
nodes.push(rootNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
function spawn (nodeText, mousePointer) {
|
||||
try {
|
||||
let point = {
|
||||
@@ -366,6 +376,32 @@ function newWorkspace () {
|
||||
functionLibraryTaskFunctions.stopAllTaskManagers(payload.node, functionLibraryProtocolNode)
|
||||
}
|
||||
break
|
||||
case 'Run All Exchange Tasks':
|
||||
{
|
||||
functionLibraryTaskFunctions.runAllExchangeTasks(payload.node, functionLibraryProtocolNode)
|
||||
}
|
||||
break
|
||||
case 'Stop All Exchange Tasks':
|
||||
{
|
||||
functionLibraryTaskFunctions.stopAllExchangeTasks(payload.node, functionLibraryProtocolNode)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Crypto Exchanges':
|
||||
{
|
||||
functionLibraryCCXTFunctions.addMissingExchanges(payload.node, functionLibraryUiObjectsFromNodes)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Assets':
|
||||
{
|
||||
functionLibraryCCXTFunctions.addMissingAssets(payload.node, functionLibraryUiObjectsFromNodes)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Markets':
|
||||
{
|
||||
functionLibraryCCXTFunctions.addMissingMarkets(payload.node, functionLibraryUiObjectsFromNodes, functionLibraryNodeCloning)
|
||||
}
|
||||
break
|
||||
|
||||
case 'Run Session':
|
||||
{
|
||||
functionLibrarySessionFunctions.runSession(payload.node, functionLibraryProtocolNode, callBackFunction)
|
||||
@@ -391,6 +427,17 @@ function newWorkspace () {
|
||||
referenceDetachNode(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Open Documentation':
|
||||
{
|
||||
let definition = APP_SCHEMA_MAP.get(payload.node.type)
|
||||
if (definition !== undefined) {
|
||||
if (definition.docURL !== undefined) {
|
||||
let newTab = window.open(definition.docURL, '_blank')
|
||||
newTab.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ function newCircularMenu () {
|
||||
|
||||
let iconAndTextArray = []
|
||||
let iconOnlyArray
|
||||
let ringsArray = [[], [], []]
|
||||
let ringsArray = [[], [], [], []]
|
||||
|
||||
for (let i = 0; i < menuItemsInitialValues.length; i++) {
|
||||
let menuItem = newCircularMenuItem()
|
||||
@@ -103,15 +103,18 @@ function newCircularMenu () {
|
||||
menuItems.push(menuItem)
|
||||
}
|
||||
|
||||
/* There are 3 possible rings of icons, we will go through each of them here. */
|
||||
let amplitudeArray = [80, 50, 40]
|
||||
let initialAngleArray = [220, 205, 200]
|
||||
for (let j = 1; j < 4; j++) {
|
||||
/* There are 4 possible rings of icons, we will go through each of them here. */
|
||||
let amplitudeArray = [80, 50, 40, 80]
|
||||
let initialAngleArray = [220, 205, 200, 180]
|
||||
for (let j = 1; j < ringsArray.length + 1; j++) {
|
||||
let iconOnlyArray = ringsArray[j - 1]
|
||||
/* Here we calculate the angles for each menu item, and then apply it if it was not previously defined. */
|
||||
let amplitude = amplitudeArray[j - 1]
|
||||
let initialAngle = initialAngleArray[j - 1]
|
||||
let step = amplitude / (iconOnlyArray.length - 1)
|
||||
if (iconOnlyArray.length === 1) {
|
||||
step = 0
|
||||
}
|
||||
|
||||
for (let i = 0; i < iconOnlyArray.length; i++) {
|
||||
let menuItem = iconOnlyArray[i]
|
||||
|
||||
@@ -57,7 +57,7 @@ function newCircularMenuItem () {
|
||||
thisObject.container.frame.position.x = 0
|
||||
thisObject.container.frame.position.y = 0
|
||||
thisObject.container.frame.width = 0
|
||||
thisObject.container.frame.height = 30
|
||||
thisObject.container.frame.height = 40
|
||||
|
||||
let isMouseOver = false
|
||||
|
||||
@@ -112,7 +112,7 @@ function newCircularMenuItem () {
|
||||
selfMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
|
||||
if (thisObject.type === 'Icon & Text') {
|
||||
thisObject.container.frame.width = 150
|
||||
thisObject.container.frame.width = 220
|
||||
} else {
|
||||
thisObject.container.frame.width = 50
|
||||
}
|
||||
@@ -150,15 +150,19 @@ function newCircularMenuItem () {
|
||||
if (thisObject.type === 'Icon Only') {
|
||||
switch (thisObject.ring) {
|
||||
case 1: {
|
||||
radiusGrowthFactor = 6
|
||||
radiusGrowthFactor = 6.5
|
||||
break
|
||||
}
|
||||
case 2: {
|
||||
radiusGrowthFactor = 4.5
|
||||
radiusGrowthFactor = 5.0
|
||||
break
|
||||
}
|
||||
case 3: {
|
||||
radiusGrowthFactor = 3
|
||||
radiusGrowthFactor = 3.5
|
||||
break
|
||||
}
|
||||
case 4: {
|
||||
radiusGrowthFactor = 2.5
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -371,13 +375,13 @@ function newCircularMenuItem () {
|
||||
backgroundColor = UI_COLOR.GREY
|
||||
}
|
||||
let params = {
|
||||
cornerRadius: 3,
|
||||
cornerRadius: 5,
|
||||
lineWidth: 0.1,
|
||||
container: thisObject.container,
|
||||
borderColor: UI_COLOR.DARK,
|
||||
backgroundColor: backgroundColor,
|
||||
castShadow: false,
|
||||
xOffset: 40
|
||||
xOffset: 60
|
||||
}
|
||||
|
||||
if (isMouseOver === true) {
|
||||
@@ -418,13 +422,13 @@ function newCircularMenuItem () {
|
||||
|
||||
if (thisObject.type === 'Icon & Text') {
|
||||
let labelPoint
|
||||
let fontSize = 10
|
||||
let fontSize = 15
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
|
||||
if (thisObject.currentRadius >= thisObject.targetRadius) {
|
||||
labelPoint = {
|
||||
x: menuPosition.x + thisObject.currentRadius + 20,
|
||||
x: menuPosition.x + thisObject.currentRadius + 25,
|
||||
y: menuPosition.y + fontSize * FONT_ASPECT_RATIO
|
||||
}
|
||||
|
||||
|
||||
@@ -55,10 +55,21 @@ function newCircularProgressBar () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
if (thisObject.payload.uiObject === undefined) { return }
|
||||
opacityCounters[message.event.seconds] = 2000
|
||||
thisObject.payload.uiObject.setValue(message.event.processingDate)
|
||||
if (message.event.processingDate !== undefined) {
|
||||
thisObject.payload.uiObject.setValue(message.event.processingDate, 2000)
|
||||
}
|
||||
if (message.event.percentage !== undefined) {
|
||||
thisObject.payload.uiObject.setPercentage(message.event.percentage, 2000)
|
||||
}
|
||||
if (message.event.status !== undefined) {
|
||||
thisObject.payload.uiObject.setStatus(message.event.status, 200000)
|
||||
}
|
||||
|
||||
thisObject.payload.uiObject.heartBeat()
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (canvas.floatingSpace.inMapMode === true) { return }
|
||||
let container
|
||||
|
||||
for (let i = 0; i < menuItems.length; i++) {
|
||||
@@ -83,6 +94,7 @@ function newCircularProgressBar () {
|
||||
}
|
||||
|
||||
function drawBackground (pFloatingObject) {
|
||||
if (canvas.floatingSpace.inMapMode === true) { return }
|
||||
const VISIBLE_RADIUS = thisObject.container.frame.radius * 2
|
||||
|
||||
let visiblePosition = {
|
||||
|
||||
@@ -129,8 +129,8 @@ function newCodeEditor () {
|
||||
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
|
||||
thisObject.container.frame.width = thisObject.container.frame.radius * 1.8 * 1.5
|
||||
thisObject.container.frame.height = thisObject.container.frame.radius * 1 * 1.4
|
||||
|
||||
let textAreaPosition = {
|
||||
x: 0 - thisObject.container.frame.width / 2,
|
||||
@@ -162,7 +162,7 @@ function newCodeEditor () {
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
let radius = thisObject.container.frame.radius * 2
|
||||
let radius = thisObject.container.frame.radius * 1.5
|
||||
|
||||
if (radius > 0.5) {
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
@@ -24,7 +24,6 @@ function newFloatingLayer () {
|
||||
removeFloatingObject: removeFloatingObject,
|
||||
getFloatingObject: getFloatingObject,
|
||||
physics: physics,
|
||||
changeTargetRepulsion: changeTargetRepulsion,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
@@ -200,10 +199,24 @@ function newFloatingLayer () {
|
||||
}
|
||||
}
|
||||
|
||||
function collapsePhysics (thisObject) {
|
||||
let parent = thisObject.payload.chainParent
|
||||
if (parent === undefined) { return }
|
||||
if (parent.payload === undefined) { return }
|
||||
if (parent.payload.floatingObject === undefined) { return }
|
||||
|
||||
thisObject.isParentCollapsed = parent.payload.floatingObject.isCollapsed
|
||||
if (thisObject.collapsedManually === false) {
|
||||
thisObject.isCollapsed = parent.payload.floatingObject.isCollapsed
|
||||
}
|
||||
}
|
||||
|
||||
function makeVisible () {
|
||||
for (let i = 0; i < invisibleFloatingObjects.length; i++) {
|
||||
let floatingObject = invisibleFloatingObjects[i]
|
||||
|
||||
collapsePhysics(floatingObject)
|
||||
|
||||
if (floatingObject.isFrozen === false && floatingObject.isParentCollapsed === false) {
|
||||
visibleFloatingObjects.push(floatingObject)
|
||||
invisibleFloatingObjects.splice(i, 1) // Delete item from array.
|
||||
@@ -217,6 +230,8 @@ function newFloatingLayer () {
|
||||
for (let i = 0; i < visibleFloatingObjects.length; i++) {
|
||||
let floatingObject = visibleFloatingObjects[i]
|
||||
|
||||
collapsePhysics(floatingObject)
|
||||
|
||||
if (floatingObject.isFrozen === true || floatingObject.isParentCollapsed === true) {
|
||||
invisibleFloatingObjects.push(floatingObject)
|
||||
visibleFloatingObjects.splice(i, 1) // Delete item from array.
|
||||
@@ -256,10 +271,8 @@ function newFloatingLayer () {
|
||||
/* This function makes all the calculations to apply phisycs on all visible floatingObjects in this layer. */
|
||||
|
||||
try {
|
||||
for (let i = 0; i < invisibleFloatingObjects.length; i++) {
|
||||
let floatingObject = invisibleFloatingObjects[i]
|
||||
floatingObject.physics()
|
||||
}
|
||||
DEBUG.variable1 = 'Invisible Floating Objets: ' + invisibleFloatingObjects.length
|
||||
DEBUG.variable2 = 'Visible Floating Objets: ' + visibleFloatingObjects.length
|
||||
|
||||
for (let i = 0; i < visibleFloatingObjects.length; i++) {
|
||||
let floatingObject = visibleFloatingObjects[i]
|
||||
@@ -605,24 +618,6 @@ function newFloatingLayer () {
|
||||
}
|
||||
}
|
||||
|
||||
function changeTargetRepulsion (pDelta) {
|
||||
try {
|
||||
if (pDelta > 0) {
|
||||
pDelta = 1
|
||||
} else {
|
||||
pDelta = -1
|
||||
}
|
||||
|
||||
maxTargetRepulsionForce = maxTargetRepulsionForce + pDelta / 1000
|
||||
|
||||
if (maxTargetRepulsionForce < 0.0000000001) {
|
||||
maxTargetRepulsionForce = 0.0000000001
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] changeTargetRepulsion -> err= ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function colliding (floatingObject1, floatingObject2) {
|
||||
try {
|
||||
/* This function detects weather 2 floatingObjects collide with each other. */
|
||||
|
||||
@@ -45,6 +45,7 @@ function newFloatingObject () {
|
||||
initializeRadius: initializeRadius,
|
||||
initializeImageSize: initializeImageSize,
|
||||
initializeFontSize: initializeFontSize,
|
||||
initializeHierarchyRing: initializeHierarchyRing,
|
||||
initializeCurrentPosition: initializeCurrentPosition,
|
||||
radomizeCurrentSpeed: radomizeCurrentSpeed,
|
||||
drawBackground: drawBackground,
|
||||
@@ -107,6 +108,7 @@ function newFloatingObject () {
|
||||
|
||||
function getContainer (point) {
|
||||
if ((thisObject.isCollapsed === true && thisObject.collapsedManually === false) || thisObject.isParentCollapsed === true) { return }
|
||||
if (canvas.floatingSpace.inMapMode === true) { return }
|
||||
let container
|
||||
|
||||
container = thisObject.payload.uiObject.getContainer(point)
|
||||
@@ -219,12 +221,13 @@ function newFloatingObject () {
|
||||
}
|
||||
|
||||
function physics () {
|
||||
collapsePhysics()
|
||||
frozenPhysics()
|
||||
/* From here on, only if they are not too far. */
|
||||
if (canvas.floatingSpace.isItFar(thisObject.payload)) { return }
|
||||
thisObjectPhysics()
|
||||
thisObject.payload.uiObject.physics()
|
||||
if (thisObject.payload.uiObject !== undefined) {
|
||||
thisObject.payload.uiObject.physics()
|
||||
}
|
||||
positionContraintsPhysics()
|
||||
}
|
||||
|
||||
@@ -241,18 +244,6 @@ function newFloatingObject () {
|
||||
}
|
||||
}
|
||||
|
||||
function collapsePhysics () {
|
||||
let parent = thisObject.payload.chainParent
|
||||
if (parent === undefined) { return }
|
||||
if (parent.payload === undefined) { return }
|
||||
if (parent.payload.floatingObject === undefined) { return }
|
||||
|
||||
thisObject.isParentCollapsed = parent.payload.floatingObject.isCollapsed
|
||||
if (thisObject.collapsedManually === false) {
|
||||
thisObject.isCollapsed = parent.payload.floatingObject.isCollapsed
|
||||
}
|
||||
}
|
||||
|
||||
function positionContraintsPhysics () {
|
||||
if (thisObject.angleToParent !== ANGLE_TO_PARENT.NOT_FIXED && thisObject.isOnFocus !== true) {
|
||||
let parent = thisObject.payload.chainParent
|
||||
@@ -330,7 +321,7 @@ function newFloatingObject () {
|
||||
|
||||
thisObject.payload.distance = distanceToParent
|
||||
|
||||
if (distanceToParent > 2000 || thisObject.isPinned === true) { return } // this is introduced to avoid edges cases when importing workspaces.
|
||||
if (distanceToParent > 3000 || thisObject.isPinned === true) { return } // this is introduced to avoid edges cases when importing workspaces.
|
||||
|
||||
newPosition = {
|
||||
x: parent.payload.position.x + distanceToParent * Math.cos(toRadians(thisObject.payload.angle)),
|
||||
@@ -348,11 +339,11 @@ function newFloatingObject () {
|
||||
function thisObjectPhysics () {
|
||||
// The radius also have a target.
|
||||
|
||||
if (Math.abs(thisObject.container.frame.radius - thisObject.targetRadius) >= 15) {
|
||||
if (Math.abs(thisObject.container.frame.radius - thisObject.targetRadius) >= 10) {
|
||||
if (thisObject.container.frame.radius < thisObject.targetRadius) {
|
||||
thisObject.container.frame.radius = thisObject.container.frame.radius + 15
|
||||
thisObject.container.frame.radius = thisObject.container.frame.radius + 10
|
||||
} else {
|
||||
thisObject.container.frame.radius = thisObject.container.frame.radius - 15
|
||||
thisObject.container.frame.radius = thisObject.container.frame.radius - 10
|
||||
}
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
}
|
||||
@@ -377,6 +368,14 @@ function newFloatingObject () {
|
||||
}
|
||||
}
|
||||
|
||||
if (Math.abs(thisObject.currentHierarchyRing - thisObject.targetHierarchyRing) >= 10) {
|
||||
if (thisObject.currentHierarchyRing < thisObject.targetHierarchyRing) {
|
||||
thisObject.currentHierarchyRing = thisObject.currentHierarchyRing + 10
|
||||
} else {
|
||||
thisObject.currentHierarchyRing = thisObject.currentHierarchyRing - 10
|
||||
}
|
||||
}
|
||||
|
||||
/* Floating object position in screen coordinates */
|
||||
|
||||
thisObject.payload.position.x = thisObject.container.frame.position.x
|
||||
@@ -388,6 +387,7 @@ function newFloatingObject () {
|
||||
thisObject.targetRadius = thisObject.rawRadius * 6.0
|
||||
thisObject.targetImageSize = thisObject.rawImageSize * 2.0
|
||||
thisObject.targetFontSize = thisObject.rawFontSize * 2.0
|
||||
thisObject.targetHierarchyRing = thisObject.rawHierarchyRing * 8.0
|
||||
|
||||
thisObject.payload.uiObject.container.eventHandler.raiseEvent('onFocus', point)
|
||||
|
||||
@@ -420,6 +420,7 @@ function newFloatingObject () {
|
||||
thisObject.targetRadius = thisObject.rawRadius * 1
|
||||
thisObject.targetImageSize = thisObject.rawImageSize * 1
|
||||
thisObject.targetFontSize = thisObject.rawFontSize * 1
|
||||
thisObject.targetHierarchyRing = thisObject.rawHierarchyRing * 1
|
||||
|
||||
thisObject.payload.uiObject.container.eventHandler.raiseEvent('onNotFocus')
|
||||
|
||||
@@ -478,13 +479,13 @@ function newFloatingObject () {
|
||||
|
||||
thisObject.rawRadius = radius
|
||||
thisObject.targetRadius = radius
|
||||
thisObject.container.frame.radius = radius / 3
|
||||
thisObject.container.frame.radius = radius / 5
|
||||
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
}
|
||||
|
||||
function initializeImageSize (suggestedValue) {
|
||||
var size = suggestedValue
|
||||
let size = suggestedValue
|
||||
if (size < 2) {
|
||||
size = 2
|
||||
}
|
||||
@@ -495,7 +496,7 @@ function newFloatingObject () {
|
||||
}
|
||||
|
||||
function initializeFontSize (suggestedValue) {
|
||||
var size = suggestedValue
|
||||
let size = suggestedValue
|
||||
if (size < 3) {
|
||||
size = 3
|
||||
}
|
||||
@@ -505,6 +506,17 @@ function newFloatingObject () {
|
||||
thisObject.currentFontSize = size / 3
|
||||
}
|
||||
|
||||
function initializeHierarchyRing (suggestedValue) {
|
||||
let radius = suggestedValue
|
||||
if (radius < 3) {
|
||||
radius = 3
|
||||
}
|
||||
|
||||
thisObject.rawHierarchyRing = radius
|
||||
thisObject.targetHierarchyRing = radius
|
||||
thisObject.currentHierarchyRing = radius
|
||||
}
|
||||
|
||||
function initializeCurrentPosition (arroundPoint) {
|
||||
let position = {}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ function newUiObject () {
|
||||
shortcutKey: undefined,
|
||||
run: run,
|
||||
stop: stop,
|
||||
heartBeat: heartBeat,
|
||||
getReadyToChainAttach: getReadyToChainAttach,
|
||||
showAvailabilityToChainAttach: showAvailabilityToChainAttach,
|
||||
getReadyToReferenceAttach: getReadyToReferenceAttach,
|
||||
@@ -32,6 +33,8 @@ function newUiObject () {
|
||||
highlight: highlight,
|
||||
setErrorMessage: setErrorMessage,
|
||||
setValue: setValue,
|
||||
setPercentage: setPercentage,
|
||||
setStatus: setStatus,
|
||||
physics: physics,
|
||||
drawBackground: drawBackground,
|
||||
drawMiddleground: drawMiddleground,
|
||||
@@ -54,7 +57,7 @@ function newUiObject () {
|
||||
let executingIcon
|
||||
|
||||
let selfFocusEventSubscriptionId
|
||||
let selfNotFocuskEventSubscriptionId
|
||||
let selfNotFocusEventSubscriptionId
|
||||
let selfDisplaceEventSubscriptionId
|
||||
let selfDragStartedEventSubscriptionId
|
||||
let selfDragFinishedEventSubscriptionId
|
||||
@@ -68,6 +71,12 @@ function newUiObject () {
|
||||
let hasValue
|
||||
let valueCounter = 0
|
||||
|
||||
let hasPercentage
|
||||
let percentageCounter = 0
|
||||
|
||||
let hasStatus
|
||||
let statusCounter = 0
|
||||
|
||||
let previousDistanceToChainParent
|
||||
let readyToChainAttachDisplayCounter = 5
|
||||
let readyToChainAttachDisplayIncrement = 0.1
|
||||
@@ -92,20 +101,29 @@ function newUiObject () {
|
||||
|
||||
let errorMessage = ''
|
||||
let currentValue = 0
|
||||
let currentPercentage = ''
|
||||
let currentStatus = ''
|
||||
let rightDragging = false
|
||||
|
||||
let eventSubscriptionIdHeartbeat
|
||||
let eventSubscriptionIdOnRunning
|
||||
let eventSubscriptionIdOnStopped
|
||||
let lastHeartBeat
|
||||
let onRunningCallBackFunction
|
||||
let onRunningCallBackFunctionWasCalled = false
|
||||
|
||||
let newUiObjectCounter = 25
|
||||
let referenceLineCounter = 0
|
||||
let chainLineCounter = 0
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdHeartbeat, 'UiObject')
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject')
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdOnStopped, 'UiObject')
|
||||
|
||||
thisObject.container.eventHandler.stopListening(selfFocusEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(selfNotFocuskEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(selfNotFocusEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(selfDisplaceEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(selfDragStartedEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(selfDragFinishedEventSubscriptionId)
|
||||
@@ -143,6 +161,9 @@ function newUiObject () {
|
||||
icon = undefined
|
||||
chainAttachToNode = undefined
|
||||
referenceAttachToNode = undefined
|
||||
lastHeartBeat = undefined
|
||||
|
||||
onRunningCallBackFunction = undefined
|
||||
}
|
||||
|
||||
function initialize (payload, menuItemsInitialValues) {
|
||||
@@ -166,7 +187,7 @@ function newUiObject () {
|
||||
iconPhysics()
|
||||
|
||||
selfFocusEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onFocus', onFocus)
|
||||
selfNotFocuskEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onNotFocus', onNotFocus)
|
||||
selfNotFocusEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onNotFocus', onNotFocus)
|
||||
selfDisplaceEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDisplace', onDisplace)
|
||||
selfDragStartedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDragStarted', onDragStarted)
|
||||
selfDragFinishedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDragFinished', onDragFinished)
|
||||
@@ -273,20 +294,62 @@ function newUiObject () {
|
||||
highlightPhisycs()
|
||||
errorMessagePhisycs()
|
||||
valuePhisycs()
|
||||
percentagePhisycs()
|
||||
statusPhisycs()
|
||||
chainDetachingPhysics()
|
||||
chainAttachingPhysics()
|
||||
referenceDetachingPhysics()
|
||||
referenceAttachingPhysics()
|
||||
childrenRunningPhysics()
|
||||
newObjectPhysics()
|
||||
referenceLinePhysics()
|
||||
chainLinePhysics()
|
||||
}
|
||||
|
||||
function referenceLinePhysics () {
|
||||
referenceLineCounter = referenceLineCounter + 2
|
||||
if (referenceLineCounter > 500) {
|
||||
referenceLineCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
function chainLinePhysics () {
|
||||
chainLineCounter = chainLineCounter - 5
|
||||
if (chainLineCounter < 0) {
|
||||
chainLineCounter = 500
|
||||
}
|
||||
}
|
||||
|
||||
function newObjectPhysics () {
|
||||
newUiObjectCounter--
|
||||
if (newUiObjectCounter < 0) {
|
||||
newUiObjectCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
function heartBeatPhysics () {
|
||||
if (lastHeartBeat !== undefined) {
|
||||
const ONE_MIN = 60000
|
||||
nowTimestamp = (new Date()).valueOf()
|
||||
if (nowTimestamp - lastHeartBeat.valueOf() > ONE_MIN) {
|
||||
lastHeartBeat = undefined
|
||||
thisObject.isRunning = false
|
||||
valueCounter = 0
|
||||
}
|
||||
} else {
|
||||
thisObject.isRunning = false
|
||||
}
|
||||
}
|
||||
|
||||
function childrenRunningPhysics () {
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition.properties === undefined) { return }
|
||||
let monitorChildrenRunning = false
|
||||
for (let i = 0; i < nodeDefinition.properties.length; i++) {
|
||||
let property = nodeDefinition.properties[i]
|
||||
if (property.monitorChildrenRunning === true) {
|
||||
let children = thisObject.payload.node[property.name]
|
||||
if (children === undefined) { continue }
|
||||
let totalRunning = 0
|
||||
for (let j = 0; j < children.length; j++) {
|
||||
let child = children[j]
|
||||
@@ -299,11 +362,15 @@ function newUiObject () {
|
||||
thisObject.isRunning = true
|
||||
} else {
|
||||
thisObject.isRunning = false
|
||||
valueCounter = 0
|
||||
}
|
||||
|
||||
monitorChildrenRunning = true
|
||||
return
|
||||
}
|
||||
}
|
||||
if (monitorChildrenRunning === false) {
|
||||
heartBeatPhysics()
|
||||
}
|
||||
}
|
||||
|
||||
function chainAttachingPhysics () {
|
||||
@@ -590,6 +657,22 @@ function newUiObject () {
|
||||
}
|
||||
}
|
||||
|
||||
function percentagePhisycs () {
|
||||
percentageCounter--
|
||||
if (percentageCounter < 0) {
|
||||
percentageCounter = 0
|
||||
hasPercentage = false
|
||||
}
|
||||
}
|
||||
|
||||
function statusPhisycs () {
|
||||
statusCounter--
|
||||
if (statusCounter < 0) {
|
||||
statusCounter = 0
|
||||
hasStatus = false
|
||||
}
|
||||
}
|
||||
|
||||
function highlight () {
|
||||
isHighlighted = true
|
||||
highlightCounter = 30
|
||||
@@ -604,11 +687,51 @@ function newUiObject () {
|
||||
}
|
||||
}
|
||||
|
||||
function setValue (value) {
|
||||
function setValue (value, counter) {
|
||||
if (value !== undefined) {
|
||||
currentValue = value
|
||||
hasValue = true
|
||||
valueCounter = 500
|
||||
if (counter !== undefined) {
|
||||
valueCounter = counter
|
||||
} else {
|
||||
valueCounter = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setPercentage (percentage, counter) {
|
||||
if (percentage !== undefined) {
|
||||
currentPercentage = percentage
|
||||
hasPercentage = true
|
||||
if (counter !== undefined) {
|
||||
percentageCounter = counter
|
||||
} else {
|
||||
percentageCounter = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setStatus (status, counter) {
|
||||
if (status !== undefined) {
|
||||
currentStatus = status
|
||||
hasStatus = true
|
||||
if (counter !== undefined) {
|
||||
statusCounter = counter
|
||||
} else {
|
||||
statusCounter = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function heartBeat () {
|
||||
lastHeartBeat = new Date()
|
||||
thisObject.isRunning = true
|
||||
|
||||
if (onRunningCallBackFunctionWasCalled === false) {
|
||||
onRunningCallBackFunctionWasCalled = true
|
||||
if (onRunningCallBackFunction !== undefined) {
|
||||
onRunningCallBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,19 +748,25 @@ function newUiObject () {
|
||||
|
||||
/* We will wait to hear the first onHeartBeat in order to confirm the execution was really started */
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.listenToEvent(key, 'Heartbeat', undefined, 'UiObject', onResponse, onHeartBeat)
|
||||
systemEventHandler.listenToEvent(key, 'Running', undefined, 'UiObject', onResponse, onRunning)
|
||||
|
||||
onRunningCallBackFunction = callBackFunction
|
||||
|
||||
function onResponse (message) {
|
||||
eventSubscriptionIdHeartbeat = message.eventSubscriptionId
|
||||
eventSubscriptionIdOnRunning = message.eventSubscriptionId
|
||||
}
|
||||
|
||||
function onHeartBeat () {
|
||||
function onRunning () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdHeartbeat, 'UiObject')
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject')
|
||||
|
||||
thisObject.isRunning = true
|
||||
|
||||
if (callBackFunction !== undefined) {
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
onRunningCallBackFunctionWasCalled = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,8 +785,6 @@ function newUiObject () {
|
||||
type: 'Secondary Action Already Executed'
|
||||
}
|
||||
stop(callBackFunction, event)
|
||||
|
||||
thisObject.isRunning = true
|
||||
}
|
||||
|
||||
function stop (callBackFunction, event) {
|
||||
@@ -680,6 +807,10 @@ function newUiObject () {
|
||||
thisObject.circularProgressBar = undefined
|
||||
}
|
||||
thisObject.isRunning = false
|
||||
hasValue = false
|
||||
hasPercentage = false
|
||||
hasStatus = false
|
||||
lastHeartBeat = undefined
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,8 +826,10 @@ function newUiObject () {
|
||||
}
|
||||
if (nodeDefinition.alternativeIcons === 'Use Reference Grandparent') {
|
||||
if (thisObject.payload.node.payload.referenceParent !== undefined) {
|
||||
if (thisObject.payload.node.payload.referenceParent.payload.referenceParent !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.referenceParent
|
||||
if (thisObject.payload.node.payload.referenceParent.payload !== undefined) {
|
||||
if (thisObject.payload.node.payload.referenceParent.payload.referenceParent !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.referenceParent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -805,6 +938,8 @@ function newUiObject () {
|
||||
function drawMiddleground () {
|
||||
if (thisObject.isOnFocus === false) {
|
||||
drawValue()
|
||||
drawPercentage()
|
||||
drawStatus()
|
||||
drawText()
|
||||
thisObject.uiObjectTitle.draw()
|
||||
}
|
||||
@@ -883,6 +1018,8 @@ function newUiObject () {
|
||||
|
||||
drawErrorMessage()
|
||||
drawValue()
|
||||
drawPercentage()
|
||||
drawStatus()
|
||||
drawText()
|
||||
|
||||
if (drawTitle === true) {
|
||||
@@ -892,6 +1029,7 @@ function newUiObject () {
|
||||
}
|
||||
|
||||
function drawChainLine () {
|
||||
if (canvas.floatingSpace.drawChainLines === false) { return }
|
||||
if (thisObject.payload.chainParent === undefined) { return }
|
||||
|
||||
let targetPoint = {
|
||||
@@ -907,6 +1045,11 @@ function newUiObject () {
|
||||
targetPoint = canvas.floatingSpace.container.frame.frameThisPoint(targetPoint)
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
targetPoint = canvas.floatingSpace.transformPointToMap(targetPoint)
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
}
|
||||
|
||||
if (thisObject.container.frame.radius > 1) {
|
||||
let LINE_STYLE = UI_COLOR.TITANIUM_YELLOW
|
||||
if (thisObject.payload.floatingObject.angleToParent !== ANGLE_TO_PARENT.NOT_FIXED) {
|
||||
@@ -915,6 +1058,18 @@ function newUiObject () {
|
||||
if (thisObject.payload.floatingObject.isFrozen === true) {
|
||||
LINE_STYLE = UI_COLOR.TURQUOISE
|
||||
}
|
||||
if (newUiObjectCounter > 0) {
|
||||
LINE_STYLE = UI_COLOR.GREY
|
||||
}
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(position.x, position.y)
|
||||
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + LINE_STYLE + ', 1)'
|
||||
browserCanvasContext.setLineDash([0, chainLineCounter, 2, 3, 0, 500 - chainLineCounter])
|
||||
browserCanvasContext.lineWidth = 2
|
||||
browserCanvasContext.stroke()
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(position.x, position.y)
|
||||
@@ -947,6 +1102,7 @@ function newUiObject () {
|
||||
}
|
||||
|
||||
function drawReferenceLine () {
|
||||
if (canvas.floatingSpace.drawReferenceLines === false) { return }
|
||||
if (thisObject.payload.referenceParent === undefined) { return }
|
||||
if (thisObject.payload.referenceParent.payload === undefined) { return }
|
||||
if (thisObject.payload.referenceParent.payload.floatingObject === undefined) { return }
|
||||
@@ -965,6 +1121,11 @@ function newUiObject () {
|
||||
targetPoint = canvas.floatingSpace.container.frame.frameThisPoint(targetPoint)
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
targetPoint = canvas.floatingSpace.transformPointToMap(targetPoint)
|
||||
}
|
||||
|
||||
let LINE_STYLE = UI_COLOR.GREY
|
||||
|
||||
if (thisObject.container.frame.radius > 1) {
|
||||
@@ -981,7 +1142,7 @@ function newUiObject () {
|
||||
browserCanvasContext.moveTo(position.x, position.y)
|
||||
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + LINE_STYLE + ', 1)'
|
||||
browserCanvasContext.setLineDash([1, 9, 2, 8, 3, 7, 4, 6, 0, 500])
|
||||
browserCanvasContext.setLineDash([0, referenceLineCounter, 1, 9, 2, 8, 3, 7, 4, 6, 0, 500 - referenceLineCounter])
|
||||
browserCanvasContext.lineWidth = 4
|
||||
browserCanvasContext.stroke()
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
@@ -1007,6 +1168,10 @@ function newUiObject () {
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
}
|
||||
|
||||
let radius = thisObject.container.frame.radius
|
||||
/* Label Text */
|
||||
let labelPoint
|
||||
@@ -1029,6 +1194,16 @@ function newUiObject () {
|
||||
y: position.y + radius * 4 / 5 + fontSize * FONT_ASPECT_RATIO + 15
|
||||
}
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
labelPoint.y = labelPoint.y - 20
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isHierarchyHead !== true) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = thisObject.payload.floatingObject.labelStrokeStyle
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
@@ -1047,6 +1222,10 @@ function newUiObject () {
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
}
|
||||
|
||||
let radius = thisObject.container.frame.radius * 3.5
|
||||
/* Label Text */
|
||||
let labelPoint
|
||||
@@ -1077,6 +1256,8 @@ function newUiObject () {
|
||||
|
||||
function drawValue () {
|
||||
if (hasValue === false) { return }
|
||||
if (canvas.floatingSpace.inMapMode === true) { return }
|
||||
// if (currentValue === undefined || currentValue === '') { return }
|
||||
|
||||
/* Text Follows */
|
||||
let position = {
|
||||
@@ -1086,7 +1267,11 @@ function newUiObject () {
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
let radius = thisObject.container.frame.radius * 1.5
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
}
|
||||
|
||||
let radius = thisObject.container.frame.radius * 1.35
|
||||
/* Label Text */
|
||||
let labelPoint
|
||||
let fontSize = thisObject.payload.floatingObject.currentFontSize * 6 / 4
|
||||
@@ -1102,6 +1287,53 @@ function newUiObject () {
|
||||
}
|
||||
}
|
||||
|
||||
if (label !== undefined) {
|
||||
if (label.length > MAX_LABEL_LENGTH) {
|
||||
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
|
||||
}
|
||||
|
||||
if (label.length > 30) {
|
||||
fontSize = fontSize / 2
|
||||
}
|
||||
|
||||
labelPoint = {
|
||||
x: position.x - label.length / 2 * fontSize * FONT_ASPECT_RATIO - 10,
|
||||
y: position.y + radius * 7 / 5 + fontSize * FONT_ASPECT_RATIO + 15
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TURQUOISE + ', 1)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawPercentage () {
|
||||
if (hasPercentage === false) { return }
|
||||
if (canvas.floatingSpace.inMapMode === true) { return }
|
||||
|
||||
let position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
}
|
||||
|
||||
let radius = thisObject.container.frame.radius * 1.75
|
||||
/* Label Text */
|
||||
let labelPoint
|
||||
let fontSize = thisObject.payload.floatingObject.currentFontSize * 6 / 4
|
||||
let label
|
||||
|
||||
if (radius > 6) {
|
||||
const MAX_LABEL_LENGTH = 65
|
||||
|
||||
label = Number(currentPercentage).toFixed(0) + '%'
|
||||
|
||||
if (label !== undefined) {
|
||||
if (label.length > MAX_LABEL_LENGTH) {
|
||||
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
|
||||
@@ -1119,6 +1351,49 @@ function newUiObject () {
|
||||
}
|
||||
}
|
||||
|
||||
function drawStatus () {
|
||||
if (hasStatus === false) { return }
|
||||
if (canvas.floatingSpace.inMapMode === true) { return }
|
||||
|
||||
let position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
}
|
||||
|
||||
let radius = thisObject.container.frame.radius * 1.4
|
||||
/* Label Text */
|
||||
let labelPoint
|
||||
let fontSize = thisObject.payload.floatingObject.currentFontSize * 6 / 4 / 2
|
||||
let label
|
||||
|
||||
if (radius > 6) {
|
||||
const MAX_LABEL_LENGTH = 65
|
||||
|
||||
label = currentStatus
|
||||
|
||||
if (label !== undefined) {
|
||||
if (label.length > MAX_LABEL_LENGTH) {
|
||||
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
|
||||
}
|
||||
|
||||
labelPoint = {
|
||||
x: position.x - label.length / 2 * fontSize * FONT_ASPECT_RATIO - 10,
|
||||
y: position.y - radius * 7 / 5 + fontSize * FONT_ASPECT_RATIO + 15
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 1)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addIndexNumber (label) {
|
||||
switch (thisObject.payload.node.type) {
|
||||
case 'Phase': {
|
||||
@@ -1189,6 +1464,10 @@ function newUiObject () {
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
position = canvas.floatingSpace.transformPointToMap(position)
|
||||
}
|
||||
|
||||
let radius = thisObject.container.frame.radius
|
||||
|
||||
if (radius > 0.5) {
|
||||
@@ -1200,7 +1479,14 @@ function newUiObject () {
|
||||
}
|
||||
|
||||
visiblePosition = thisObject.container.frame.frameThisPoint(visiblePosition)
|
||||
visiblePosition = thisObject.fitFunction(visiblePosition)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
visiblePosition = canvas.floatingSpace.transformPointToMap(visiblePosition)
|
||||
radius = canvas.floatingSpace.transformRadiusToMap(radius)
|
||||
VISIBLE_RADIUS = canvas.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
|
||||
} else {
|
||||
visiblePosition = thisObject.fitFunction(visiblePosition)
|
||||
}
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
@@ -1221,7 +1507,10 @@ function newUiObject () {
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isHierarchyHead === true) {
|
||||
VISIBLE_RADIUS = thisObject.container.frame.radius * 2
|
||||
VISIBLE_RADIUS = thisObject.payload.floatingObject.currentHierarchyRing * 2.8
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
VISIBLE_RADIUS = canvas.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
|
||||
}
|
||||
let OPACITY = 1
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
@@ -1391,7 +1680,15 @@ function newUiObject () {
|
||||
let additionalImageSize = 0
|
||||
if (thisObject.isExecuting === true || isReadyToReferenceAttach === true || isReadyToChainAttach === true) { additionalImageSize = 20 }
|
||||
let totalImageSize = additionalImageSize + thisObject.payload.floatingObject.currentImageSize
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
totalImageSize = canvas.floatingSpace.transformImagesizeToMap(totalImageSize)
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isHierarchyHead !== true) {
|
||||
totalImageSize = totalImageSize / 4
|
||||
}
|
||||
}
|
||||
}
|
||||
browserCanvasContext.drawImage(
|
||||
icon, position.x - totalImageSize / 2,
|
||||
position.y - totalImageSize / 2,
|
||||
@@ -1416,3 +1713,4 @@ function newUiObject () {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ function newUiObjectConstructor () {
|
||||
for (let j = 0; j < menuItems.length; j++) {
|
||||
let item = menuItems[j]
|
||||
item.angle = undefined
|
||||
if (item.action.indexOf('Add ') >= 0 && item.action.indexOf('Missing') >= 0) {
|
||||
if (item.action.indexOf('Add Missing Children') >= 0) {
|
||||
item.action = 'Add Missing Children'
|
||||
}
|
||||
if (item.action.indexOf('Delete ') >= 0) {
|
||||
@@ -134,7 +134,7 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'menu-fix-pinned',
|
||||
iconPathOff: 'menu-fix-unpinned',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
@@ -149,7 +149,7 @@ function newUiObjectConstructor () {
|
||||
label: undefined,
|
||||
visible: true,
|
||||
icons: ['angle-to-parent-000', 'angle-to-parent-360', 'angle-to-parent-180', 'angle-to-parent-090', 'angle-to-parent-045'],
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
@@ -164,7 +164,7 @@ function newUiObjectConstructor () {
|
||||
label: undefined,
|
||||
visible: true,
|
||||
icons: ['distance-to-parent-000', 'distance-to-parent-025', 'distance-to-parent-050', 'distance-to-parent-100', 'distance-to-parent-150', 'distance-to-parent-200'],
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
@@ -180,7 +180,7 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'menu-mobility-unfreeze',
|
||||
iconPathOff: 'menu-mobility-freeze',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
@@ -196,7 +196,7 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'menu-tree-plus',
|
||||
iconPathOff: 'menu-tree-minus',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
@@ -210,7 +210,7 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'menu-backup',
|
||||
iconPathOff: 'menu-backup',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 2
|
||||
@@ -224,7 +224,7 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'clone',
|
||||
iconPathOff: 'clone',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 2
|
||||
@@ -239,7 +239,7 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'menu-share',
|
||||
iconPathOff: 'menu-share',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 2
|
||||
@@ -254,7 +254,7 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'detach',
|
||||
iconPathOff: 'detach',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 3
|
||||
@@ -268,12 +268,27 @@ function newUiObjectConstructor () {
|
||||
visible: true,
|
||||
iconPathOn: 'delink',
|
||||
iconPathOff: 'delink',
|
||||
rawRadius: 8,
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 3
|
||||
}
|
||||
)
|
||||
|
||||
menuItemsInitialValues.push(
|
||||
{
|
||||
action: 'Open Documentation',
|
||||
actionFunction: floatingObject.payload.onMenuItemClick,
|
||||
label: undefined,
|
||||
visible: true,
|
||||
iconPathOn: 'help',
|
||||
iconPathOff: 'help',
|
||||
rawRadius: 12,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 4
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function getMenuItemsInitialValues (uiObject, floatingObject, payload) {
|
||||
@@ -332,7 +347,7 @@ function newUiObjectConstructor () {
|
||||
}
|
||||
|
||||
if (newMenuItem.rawRadius === undefined) {
|
||||
newMenuItem.rawRadius = 8
|
||||
newMenuItem.rawRadius = 12
|
||||
}
|
||||
|
||||
if (newMenuItem.targetRadius === undefined) {
|
||||
@@ -355,7 +370,10 @@ function newUiObjectConstructor () {
|
||||
function setFloatingObjectBasicProperties (floatingObject, payload) {
|
||||
const FRICTION = 0.95
|
||||
const INITIAL_FRICTION = 0.97
|
||||
const INITIAL_FONT_SIZE = 12
|
||||
const INITIAL_FONT_SIZE = 12 * 1.5
|
||||
const INITIAL_RADIOUS = 45 * 1.5
|
||||
const INITIAL_IMAGE_SIZE = 80 * 1.2
|
||||
const INITIAL_HIERARCHY_RING = 20
|
||||
|
||||
switch (payload.node.type) {
|
||||
case 'Workspace': {
|
||||
@@ -402,8 +420,9 @@ function newUiObjectConstructor () {
|
||||
floatingObject.friction = INITIAL_FRICTION
|
||||
|
||||
floatingObject.initializeMass(500)
|
||||
floatingObject.initializeRadius(45)
|
||||
floatingObject.initializeImageSize(80)
|
||||
floatingObject.initializeRadius(INITIAL_RADIOUS)
|
||||
floatingObject.initializeHierarchyRing(INITIAL_HIERARCHY_RING)
|
||||
floatingObject.initializeImageSize(INITIAL_IMAGE_SIZE)
|
||||
floatingObject.initializeFontSize(INITIAL_FONT_SIZE)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
@@ -413,8 +432,9 @@ function newUiObjectConstructor () {
|
||||
floatingObject.friction = INITIAL_FRICTION
|
||||
|
||||
floatingObject.initializeMass(600)
|
||||
floatingObject.initializeRadius(45)
|
||||
floatingObject.initializeImageSize(80)
|
||||
floatingObject.initializeRadius(INITIAL_RADIOUS)
|
||||
floatingObject.initializeHierarchyRing(INITIAL_HIERARCHY_RING)
|
||||
floatingObject.initializeImageSize(INITIAL_IMAGE_SIZE)
|
||||
floatingObject.initializeFontSize(INITIAL_FONT_SIZE)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
@@ -428,8 +448,9 @@ function newUiObjectConstructor () {
|
||||
floatingObject.friction = INITIAL_FRICTION
|
||||
|
||||
floatingObject.initializeMass(300)
|
||||
floatingObject.initializeRadius(40)
|
||||
floatingObject.initializeImageSize(70)
|
||||
floatingObject.initializeRadius(INITIAL_RADIOUS - 5)
|
||||
floatingObject.initializeHierarchyRing(INITIAL_HIERARCHY_RING)
|
||||
floatingObject.initializeImageSize(INITIAL_IMAGE_SIZE - 10)
|
||||
floatingObject.initializeFontSize(INITIAL_FONT_SIZE)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', 1)'
|
||||
@@ -443,8 +464,9 @@ function newUiObjectConstructor () {
|
||||
floatingObject.friction = INITIAL_FRICTION
|
||||
|
||||
floatingObject.initializeMass(150)
|
||||
floatingObject.initializeRadius(35)
|
||||
floatingObject.initializeImageSize(60)
|
||||
floatingObject.initializeRadius(INITIAL_RADIOUS - 10)
|
||||
floatingObject.initializeHierarchyRing(INITIAL_HIERARCHY_RING)
|
||||
floatingObject.initializeImageSize(INITIAL_IMAGE_SIZE - 20)
|
||||
floatingObject.initializeFontSize(INITIAL_FONT_SIZE)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', 1)'
|
||||
@@ -458,8 +480,9 @@ function newUiObjectConstructor () {
|
||||
floatingObject.friction = INITIAL_FRICTION
|
||||
|
||||
floatingObject.initializeMass(75)
|
||||
floatingObject.initializeRadius(30)
|
||||
floatingObject.initializeImageSize(50)
|
||||
floatingObject.initializeRadius(INITIAL_RADIOUS - 15)
|
||||
floatingObject.initializeHierarchyRing(INITIAL_HIERARCHY_RING)
|
||||
floatingObject.initializeImageSize(INITIAL_IMAGE_SIZE - 30)
|
||||
floatingObject.initializeFontSize(INITIAL_FONT_SIZE)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 1)'
|
||||
@@ -473,8 +496,9 @@ function newUiObjectConstructor () {
|
||||
floatingObject.friction = INITIAL_FRICTION
|
||||
|
||||
floatingObject.initializeMass(50)
|
||||
floatingObject.initializeRadius(25)
|
||||
floatingObject.initializeImageSize(40)
|
||||
floatingObject.initializeRadius(INITIAL_RADIOUS - 20)
|
||||
floatingObject.initializeHierarchyRing(INITIAL_HIERARCHY_RING)
|
||||
floatingObject.initializeImageSize(INITIAL_IMAGE_SIZE - 40)
|
||||
floatingObject.initializeFontSize(INITIAL_FONT_SIZE)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.RED + ', 1)'
|
||||
@@ -484,8 +508,9 @@ function newUiObjectConstructor () {
|
||||
floatingObject.friction = INITIAL_FRICTION
|
||||
|
||||
floatingObject.initializeMass(25)
|
||||
floatingObject.initializeRadius(20)
|
||||
floatingObject.initializeImageSize(30)
|
||||
floatingObject.initializeRadius(INITIAL_RADIOUS - 25)
|
||||
floatingObject.initializeHierarchyRing(INITIAL_HIERARCHY_RING)
|
||||
floatingObject.initializeImageSize(INITIAL_IMAGE_SIZE - 50)
|
||||
floatingObject.initializeFontSize(INITIAL_FONT_SIZE)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.RED + ', 1)'
|
||||
|
||||
@@ -136,6 +136,20 @@ function newUiObjectTitle () {
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Use Reference Parent Parent Parent': {
|
||||
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode.payload.parentNode
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
||||
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
default: {
|
||||
if (titleReference.indexOf('Use Child @') === 0) {
|
||||
let propertyName = titleReference.substring(titleReference.indexOf('@') + 1, titleReference.length)
|
||||
@@ -215,6 +229,8 @@ function newUiObjectTitle () {
|
||||
thisObject.payload.node.name = input.value
|
||||
}
|
||||
}
|
||||
let inputDiv = document.getElementById('inputDiv')
|
||||
inputDiv.style = 'position:absolute; top:' + '-100' + 'px; left:' + '-100' + 'px; z-index:1; '
|
||||
}
|
||||
|
||||
function enterEditMode () {
|
||||
@@ -292,6 +308,19 @@ function newUiObjectTitle () {
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
|
||||
if (canvas.floatingSpace.inMapMode === true) {
|
||||
labelPoint = canvas.floatingSpace.transformPointToMap(labelPoint)
|
||||
labelPoint.x = labelPoint.x - label.length / 2 * fontSize * FONT_ASPECT_RATIO
|
||||
labelPoint.y = labelPoint.y - 35
|
||||
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isHierarchyHead !== true) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = thisObject.payload.floatingObject.labelStrokeStyle
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
@@ -309,3 +338,4 @@ function newUiObjectTitle () {
|
||||
return title
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -81,13 +81,13 @@ function newFrame () {
|
||||
/* This function is usefull to know if the object who has this frame is currently appearing at least in part at the canvas.chartingSpace.viewport */
|
||||
|
||||
point1 = {
|
||||
x: thisObject.width * 25 / 100,
|
||||
y: thisObject.height * 25 / 100
|
||||
x: thisObject.width * 40 / 100,
|
||||
y: thisObject.height * 40 / 100
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.width * 75 / 100,
|
||||
y: thisObject.height * 75 / 100
|
||||
x: thisObject.width * 40 / 100,
|
||||
y: thisObject.height * 40 / 100
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
@@ -209,7 +209,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))
|
||||
|
||||
|
||||
+21
-28
@@ -3,20 +3,7 @@
|
||||
|
||||
const CANVAS_APP_NAME = 'Canvas App'
|
||||
|
||||
const SUPPORTED_EXCHANGES = ["Poloniex"];
|
||||
const SUPPORTED_MARKETS = [
|
||||
{
|
||||
baseAsset: "USDT",
|
||||
quotedAsset: "BTC",
|
||||
}
|
||||
];
|
||||
const DEFAULT_EXCHANGE = "Poloniex";
|
||||
const DEFAULT_MARKET = {
|
||||
baseAsset: "USDT",
|
||||
quotedAsset: "BTC",
|
||||
};
|
||||
|
||||
UI_COLOR = {
|
||||
const UI_COLOR = {
|
||||
DARK: "48, 48, 54",
|
||||
LIGHT: "234, 226, 222",
|
||||
GREY: "150, 150, 150",
|
||||
@@ -36,18 +23,26 @@ UI_COLOR = {
|
||||
|
||||
/* User Interface Fonts */
|
||||
|
||||
UI_FONT = {
|
||||
const UI_FONT = {
|
||||
PRIMARY: "Saira Condensed",
|
||||
SECONDARY: "Source Code Pro"
|
||||
};
|
||||
|
||||
const MAC_AMOUNT_FACTOR = 5
|
||||
const IS_MAC = navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||
|
||||
const DOUBLE_CLICK_ZOOM_OUT_LEVEL = 0
|
||||
const DOUBLE_CLICK_ZOOM_IN_LEVEL = 6
|
||||
const DOUBLE_CLICK_ZOOM_IN_IN_LEVEL = 7
|
||||
|
||||
const DEBUG = {}
|
||||
const ZOOM_OUT_THRESHOLD_FOR_HIDDING_PANELS = 5 // This regulates some behavious changes that happens when the user zoom out below this level.
|
||||
const ZOOM_OUT_THRESHOLD_FOR_CHANGING_TIME_FRAME = 5 // This help regulate when to change the Time Frame base on the level of zoom out.
|
||||
const ZOOM_OUT_THRESHOLD_FOR_NOT_HIDDING_PANELS = 12
|
||||
const ZOOM_OUT_THRESHOLD_FOR_HIDDING_PANELS = 7
|
||||
const ZOOM_OUT_THRESHOLD_FOR_CHANGING_TIME_FRAME = 3 // This help regulate when to change the Time Frame base on the level of zoom out.
|
||||
const ZOOM_OUT_THRESHOLD_FOR_PACKING_OBJECTS_AT_THE_BOTTOM_OR_TOP_OF_VIEWPORT = 2
|
||||
const ZOOM_OUT_THRESHOLD_FOR_PLOTTING_IN_LOW_RESOLUTION = 3
|
||||
const ZOOM_OUT_THRESHOLD_FOR_DISPLAYING_TIME_MACHINES_ICONIZED = 5
|
||||
const ZOOM_OUT_THRESHOLD_FOR_DISPLAYING_SCALES = 3
|
||||
const ZOOM_OUT_THRESHOLD_FOR_PLOTTING_IN_LOW_RESOLUTION = 3
|
||||
const ZOOM_OUT_THRESHOLD_FOR_DISPLAYING_TIME_MACHINES_ICONIZED = 5
|
||||
const ZOOM_OUT_THRESHOLD_FOR_DISPLAYING_SCALES = 3
|
||||
|
||||
let FONT_ASPECT_RATIO = 0.32;
|
||||
|
||||
@@ -78,7 +73,7 @@ const DISTANCE_TO_PARENT = {
|
||||
|
||||
/* User Interface Panels */
|
||||
|
||||
UI_PANEL = {
|
||||
const UI_PANEL = {
|
||||
WIDTH: {
|
||||
SMALL: 100,
|
||||
NORMAL: 150,
|
||||
@@ -124,7 +119,7 @@ let dailyFilePeriods =
|
||||
|
||||
dailyFilePeriods = JSON.parse(dailyFilePeriods);
|
||||
|
||||
SHOW_ANIMATION_PERFORMACE = false;
|
||||
let SHOW_ANIMATION_PERFORMACE = false;
|
||||
|
||||
let testUser = window.localStorage.getItem("test_user")
|
||||
let LOGGED_IN_USER_LOCAL_STORAGE_KEY
|
||||
@@ -138,10 +133,6 @@ if (testUser !== null) {
|
||||
LOGGED_IN_ACCESS_TOKEN_LOCAL_STORAGE_KEY = "access_token"
|
||||
}
|
||||
|
||||
const DEFAULT_CONFIG_TEXT = '// Write your config here'
|
||||
const DEFAULT_FORMULA_TEXT = '// Write your formula here'
|
||||
const DEFAULT_CODE_TEXT = '// Write your code here'
|
||||
|
||||
const MAX_DEFAULT_RATE_SCALE_VALUE = 35000; // This is needed to know the scale of the market time line.
|
||||
|
||||
const WIDHTER_VOLUME_BAR_BASE_FACTOR = 2.5;
|
||||
@@ -168,6 +159,8 @@ const _3_MINUTES_IN_MILISECONDS = 3 * 60 * 1000;
|
||||
const _2_MINUTES_IN_MILISECONDS = 2 * 60 * 1000;
|
||||
const _1_MINUTE_IN_MILISECONDS = 1 * 60 * 1000;
|
||||
|
||||
|
||||
|
||||
let NEW_SESSION_INITIAL_DATE = new Date(); // This value will be overwritten at the canvas.chartingSpace.viewport.initialize if the user had a prevous session with this same browser.
|
||||
let INITIAL_ZOOM_LEVEL = -28.25 // This is the zoom level at the view port in which the APP starts.
|
||||
let INITIAL_TIME_PERIOD = ONE_DAY_IN_MILISECONDS // This value will be overwritten at the canvas.chartingSpace.viewport.initialize if the user had a prevous session with this same browser.
|
||||
@@ -213,8 +206,8 @@ const PERIOD_01_MIN = "01-min";
|
||||
We define here the size of the chartingSpace. It has to bee enough big in order to accomodate all the charts we expect to display in this space.
|
||||
*/
|
||||
|
||||
const TIME_MACHINE_WIDTH = 320;
|
||||
const TIME_MACHINE_HEIGHT = 120;
|
||||
const TIME_MACHINE_WIDTH = 8;
|
||||
const TIME_MACHINE_HEIGHT = 8;
|
||||
|
||||
let mediaRecorder // to downloadText canvas animation as a mediaRecorder
|
||||
let areWeRecording = false
|
||||
|
||||
@@ -20,6 +20,7 @@ function newLayer () {
|
||||
plotterTypeIcon: undefined,
|
||||
baseAssetIcon: undefined,
|
||||
quotedAssetIcon: undefined,
|
||||
checkStatusAtShutDown: checkStatusAtShutDown,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
turnOff: turnOff,
|
||||
@@ -230,6 +231,17 @@ function newLayer () {
|
||||
}
|
||||
}
|
||||
|
||||
function checkStatusAtShutDown () {
|
||||
/* Mechanism to recover a layer that was left loading the last time the browser was shut dowm. */
|
||||
let storedValue = loadPropertyFromNodeConfig(thisObject.payload, 'status')
|
||||
if (storedValue !== undefined) {
|
||||
if (storedValue === LAYER_STATUS.LOADING) {
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.LOADING)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (panelsVisibleButton !== undefined) {
|
||||
let container = panelsVisibleButton.getContainer(point)
|
||||
|
||||
@@ -6,7 +6,8 @@ function newLayersPanel () {
|
||||
layers: [],
|
||||
payload: undefined,
|
||||
isVisible: true,
|
||||
panelTabButton: undefined,
|
||||
upDownButton: undefined,
|
||||
leftRightButton: undefined,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
@@ -21,7 +22,6 @@ function newLayersPanel () {
|
||||
thisObject.container.detectMouseOver = true
|
||||
|
||||
let isInitialized = false
|
||||
let isMouseOver = false
|
||||
let mouseOverCounter = 0
|
||||
|
||||
let layersMap = new Map()
|
||||
@@ -39,15 +39,23 @@ function newLayersPanel () {
|
||||
let posiblePanelHeight = (layerHeight + LAYER_SEPARATION) * posibleVisibleLayers + headerHeight + footerHeight
|
||||
|
||||
let onMouseWheelEventSuscriptionId
|
||||
let onMouseOverEventSuscriptionId
|
||||
let onMouseOverEventSubscriptionId
|
||||
let onMouseNotOverEventSubscriptionId
|
||||
|
||||
let isMouseOver
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseWheelEventSuscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
|
||||
|
||||
thisObject.upDownButton.finalize()
|
||||
thisObject.upDownButton = undefined
|
||||
|
||||
thisObject.leftRightButton.finalize()
|
||||
thisObject.leftRightButton = undefined
|
||||
|
||||
thisObject.panelTabButton.finalize()
|
||||
thisObject.panelTabButton = undefined
|
||||
layersMap = undefined
|
||||
visibleLayers = undefined
|
||||
|
||||
@@ -72,26 +80,45 @@ function newLayersPanel () {
|
||||
thisObject.container.frame.position = position
|
||||
loadFrame(thisObject.payload, thisObject.container.frame)
|
||||
|
||||
thisObject.panelTabButton = newPanelTabButton()
|
||||
thisObject.panelTabButton.parentContainer = thisObject.container
|
||||
thisObject.panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
thisObject.panelTabButton.fitFunction = thisObject.fitFunction
|
||||
thisObject.panelTabButton.initialize()
|
||||
thisObject.upDownButton = newUpDownButton()
|
||||
thisObject.upDownButton.parentContainer = thisObject.container
|
||||
thisObject.upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
thisObject.upDownButton.fitFunction = thisObject.fitFunction
|
||||
thisObject.upDownButton.initialize()
|
||||
|
||||
thisObject.leftRightButton = newLeftRightButton()
|
||||
thisObject.leftRightButton.parentContainer = thisObject.container
|
||||
thisObject.leftRightButton.container.frame.parentFrame = thisObject.container.frame
|
||||
thisObject.leftRightButton.fitFunction = thisObject.fitFunction
|
||||
thisObject.leftRightButton.initialize()
|
||||
|
||||
onMouseWheelEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
|
||||
readObjectState()
|
||||
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
isMouseOver = true
|
||||
}
|
||||
|
||||
function onMouseNotOver () {
|
||||
isMouseOver = false
|
||||
}
|
||||
|
||||
function saveObjectStateVisibleLayers () {
|
||||
savePropertyAtNodeConfig(thisObject.payload, 'visibleLayers', desiredVisibleLayers)
|
||||
}
|
||||
|
||||
function saveObjectStatePanelLocation () {
|
||||
savePropertyAtNodeConfig(thisObject.payload, 'panelLocation', thisObject.panelTabButton.status)
|
||||
let panelLocation = {
|
||||
upOrDown: thisObject.upDownButton.status,
|
||||
leftOrRight: thisObject.leftRightButton.status
|
||||
}
|
||||
savePropertyAtNodeConfig(thisObject.payload, 'panelLocation', panelLocation)
|
||||
}
|
||||
|
||||
function readObjectState () {
|
||||
@@ -123,11 +150,16 @@ function newLayersPanel () {
|
||||
saveObjectStatePanelLocation() // this overrides any invalid value at the config.
|
||||
return
|
||||
} else {
|
||||
if (storedValue !== 'up' && storedValue !== 'down') {
|
||||
if (storedValue.upOrDown !== 'up' && storedValue.upOrDown !== 'down') {
|
||||
saveObjectStatePanelLocation() // this overrides any invalid value at the config.
|
||||
return
|
||||
}
|
||||
thisObject.panelTabButton.setStatus(storedValue)
|
||||
if (storedValue.leftOrRight !== 'left' && storedValue.leftOrRight !== 'right') {
|
||||
saveObjectStatePanelLocation() // this overrides any invalid value at the config.
|
||||
return
|
||||
}
|
||||
thisObject.upDownButton.setStatus(storedValue.upOrDown)
|
||||
thisObject.leftRightButton.setStatus(storedValue.leftOrRight)
|
||||
saveObjectStatePanelLocation()
|
||||
}
|
||||
}
|
||||
@@ -167,16 +199,13 @@ function newLayersPanel () {
|
||||
layer.onLayerStatusChangedEventSuscriptionId = layer.container.eventHandler.listenToEvent('Status Changed', onLayerStatusChanged)
|
||||
layer.onMouseWheelEventSuscriptionId = layer.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
|
||||
return layer
|
||||
layer.checkStatusAtShutDown()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
isMouseOver = true
|
||||
mouseOverCounter = 150
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
delta = event.wheelDelta
|
||||
if (delta > 0) {
|
||||
@@ -254,8 +283,13 @@ function newLayersPanel () {
|
||||
if (isInitialized === false || thisObject.visible === false || thisObject.isHidden === true) { return }
|
||||
let container
|
||||
|
||||
container = thisObject.panelTabButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
if (isMouseOver === true && purpose !== GET_CONTAINER_PURPOSE.MOUSE_OVER) {
|
||||
container = thisObject.upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
container = thisObject.leftRightButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
}
|
||||
|
||||
/* First we check if thisObject point is inside thisObject space. */
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
@@ -304,19 +338,12 @@ function newLayersPanel () {
|
||||
readObjectState()
|
||||
}
|
||||
|
||||
function mouseOverPhysics () {
|
||||
mouseOverCounter--
|
||||
if (mouseOverCounter < 0) {
|
||||
mouseOverCounter = 0
|
||||
isMouseOver = false
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (isInitialized === false) { return }
|
||||
if (thisObject.payload.node === undefined) { return }
|
||||
|
||||
mouseOverPhysics()
|
||||
thisObject.panelTabButton.physics()
|
||||
thisObject.upDownButton.physics()
|
||||
thisObject.leftRightButton.physics()
|
||||
saveFrame(thisObject.payload, thisObject.container.frame)
|
||||
syncWithConfigPhysics()
|
||||
|
||||
@@ -344,6 +371,7 @@ function newLayersPanel () {
|
||||
calculateVisbleLayers()
|
||||
|
||||
function syncWithDesignerLayers () {
|
||||
if (thisObject.payload.node === undefined) { return }
|
||||
let layerManager = thisObject.payload.node
|
||||
for (let p = 0; p < layerManager.layers.length; p++) {
|
||||
let layerNode = layerManager.layers[p]
|
||||
@@ -392,7 +420,7 @@ function newLayersPanel () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (isInitialized === false || thisObject.visible === false || thisObject.isHidden === true || isMouseOver === false) { return }
|
||||
if (isInitialized === false || thisObject.visible === false || thisObject.isHidden === true) { return }
|
||||
|
||||
// thisObject.container.frame.draw(false, false, false, thisObject.fitFunction)
|
||||
|
||||
@@ -401,10 +429,18 @@ function newLayersPanel () {
|
||||
visibleLayers[i].draw()
|
||||
}
|
||||
drawScrollBar()
|
||||
thisObject.panelTabButton.draw()
|
||||
if (isMouseOver === true) {
|
||||
thisObject.upDownButton.draw()
|
||||
thisObject.leftRightButton.draw()
|
||||
}
|
||||
}
|
||||
|
||||
function drawHeader () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
if (thisObject.payload.node === undefined) { return }
|
||||
if (thisObject.payload.node.payload.parentNode === undefined) { return }
|
||||
if (thisObject.payload.node.payload.parentNode.payload.parentNode === undefined) { return }
|
||||
|
||||
let label1 = thisObject.payload.node.payload.parentNode.payload.parentNode.name.substring(0, 18)
|
||||
let label2 = thisObject.payload.node.payload.parentNode.name.substring(0, 18)
|
||||
let label3 = ''
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
function newLeftRightButton () {
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
parentContainer: undefined,
|
||||
status: undefined,
|
||||
setStatus: setStatus,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let isInitialized = false
|
||||
/* Cointainer stuff */
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.name = 'Left Right Button'
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isClickeable = true
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.frame.containerName = 'Left Right Button'
|
||||
|
||||
thisObject.status = 'left'
|
||||
let leftPosition = {}
|
||||
let rightPosition = {}
|
||||
let transitionPosition = {}
|
||||
|
||||
let onMouseClickEventSuscriptionId
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseClickEventSuscriptionId)
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.parentContainer = undefined
|
||||
|
||||
thisObject.status = undefined
|
||||
leftPosition = undefined
|
||||
rightPosition = undefined
|
||||
transitionPosition = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.frame.width = 12
|
||||
thisObject.container.frame.height = 12
|
||||
|
||||
let position = {
|
||||
x: thisObject.container.frame.parentFrame.width * 2.25 / 8 - thisObject.container.frame.width / 2,
|
||||
y: 40 * 4 / 8 - thisObject.container.frame.height / 2
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
|
||||
leftPosition.x = thisObject.parentContainer.frame.position.x
|
||||
leftPosition.y = thisObject.parentContainer.frame.position.y
|
||||
|
||||
rightPosition.x = thisObject.parentContainer.frame.position.x
|
||||
rightPosition.y = canvas.chartingSpace.viewport.visibleArea.bottomRight.y
|
||||
|
||||
transitionPosition.x = leftPosition.x
|
||||
transitionPosition.y = leftPosition.y
|
||||
|
||||
/* Lets listen to our own events to react when we have a Mouse Click */
|
||||
onMouseClickEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function setStatus (value) {
|
||||
if (value === 'left' && thisObject.status === 'right') {
|
||||
thisObject.status = 'going left'
|
||||
}
|
||||
if (value === 'right' && thisObject.status === 'left') {
|
||||
thisObject.status = 'going right'
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
if (thisObject.status === 'left') {
|
||||
transitionPosition.x = leftPosition.x
|
||||
transitionPosition.y = leftPosition.y
|
||||
|
||||
thisObject.status = 'going right'
|
||||
} else {
|
||||
transitionPosition.x = rightPosition.x
|
||||
transitionPosition.y = rightPosition.y
|
||||
|
||||
thisObject.status = 'going left'
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (isInitialized === false) { return }
|
||||
|
||||
leftPosition.x = canvas.chartingSpace.viewport.visibleArea.topLeft.x
|
||||
leftPosition.y = thisObject.parentContainer.frame.position.y
|
||||
|
||||
rightPosition.x = canvas.chartingSpace.viewport.visibleArea.bottomRight.x
|
||||
rightPosition.y = thisObject.parentContainer.frame.position.y
|
||||
|
||||
if (thisObject.status === 'going right') {
|
||||
if (transitionPosition.x < rightPosition.x) {
|
||||
transitionPosition.x = transitionPosition.x + 50
|
||||
thisObject.parentContainer.frame.position.x = transitionPosition.x
|
||||
} else {
|
||||
thisObject.parentContainer.frame.position.x = rightPosition.x
|
||||
thisObject.status = 'right'
|
||||
}
|
||||
}
|
||||
if (thisObject.status === 'going left') {
|
||||
if (transitionPosition.x > leftPosition.x) {
|
||||
transitionPosition.x = transitionPosition.x - 50
|
||||
thisObject.parentContainer.frame.position.x = transitionPosition.x
|
||||
} else {
|
||||
thisObject.parentContainer.frame.position.x = leftPosition.x
|
||||
thisObject.status = 'left'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (isInitialized === false) { return }
|
||||
|
||||
drawButton()
|
||||
}
|
||||
|
||||
function getContainer (point, purpose) {
|
||||
let container
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
}
|
||||
}
|
||||
|
||||
function drawButton () {
|
||||
let point1
|
||||
let point2
|
||||
let point3
|
||||
|
||||
switch (thisObject.status) {
|
||||
case 'left': {
|
||||
point1 = {
|
||||
x: 3,
|
||||
y: 3
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: 3,
|
||||
y: thisObject.container.frame.height - 3
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.container.frame.width - 3,
|
||||
y: thisObject.container.frame.height / 2
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'going right': {
|
||||
point1 = {
|
||||
x: 4,
|
||||
y: 4
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: 4,
|
||||
y: thisObject.container.frame.height - 4
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.container.frame.width - 4,
|
||||
y: thisObject.container.frame.height / 2
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'going left': {
|
||||
point1 = {
|
||||
x: thisObject.container.frame.width - 4,
|
||||
y: 4
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: thisObject.container.frame.width - 4,
|
||||
y: thisObject.container.frame.height - 4
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: 4,
|
||||
y: thisObject.container.frame.height / 2
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'right': {
|
||||
point1 = {
|
||||
x: thisObject.container.frame.width - 3,
|
||||
y: 3
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: thisObject.container.frame.width - 3,
|
||||
y: thisObject.container.frame.height - 3
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: 3,
|
||||
y: thisObject.container.frame.height / 2
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
point2 = thisObject.container.frame.frameThisPoint(point2)
|
||||
point3 = thisObject.container.frame.frameThisPoint(point3)
|
||||
|
||||
if (thisObject.fitFunction !== undefined) {
|
||||
point1 = thisObject.fitFunction(point1)
|
||||
point2 = thisObject.fitFunction(point2)
|
||||
point3 = thisObject.fitFunction(point3)
|
||||
}
|
||||
|
||||
/* Lets start the drawing. */
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y)
|
||||
browserCanvasContext.lineTo(point1.x, point1.y)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(250, 250, 250, 1)'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(250, 250, 250, 1)'
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ function newPlotterPanel () {
|
||||
|
||||
let heightFactor = 1
|
||||
let currentRecord
|
||||
let panelTabButton
|
||||
let upDownButton
|
||||
let panelNode
|
||||
|
||||
return thisObject
|
||||
@@ -35,8 +35,8 @@ function newPlotterPanel () {
|
||||
|
||||
heightFactor = undefined
|
||||
currentRecord = undefined
|
||||
panelTabButton.finalize()
|
||||
panelTabButton = undefined
|
||||
upDownButton.finalize()
|
||||
upDownButton = undefined
|
||||
panelNode = undefined
|
||||
}
|
||||
|
||||
@@ -50,18 +50,18 @@ function newPlotterPanel () {
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width - thisObject.container.frame.width * Math.random() * 8
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.bottomLeft.y - thisObject.container.frame.height - thisObject.container.frame.height * Math.random() * 1.5
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
panelTabButton.fitFunction = thisObject.fitFunction
|
||||
panelTabButton.initialize()
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container
|
||||
|
||||
container = panelTabButton.getContainer(point)
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
@@ -87,7 +87,7 @@ function newPlotterPanel () {
|
||||
|
||||
thisObject.container.frame.draw(false, false, true, thisObject.fitFunction)
|
||||
plotCurrentRecordData()
|
||||
panelTabButton.draw()
|
||||
upDownButton.draw()
|
||||
}
|
||||
|
||||
function plotCurrentRecordData () {
|
||||
@@ -153,33 +153,8 @@ function newPlotterPanel () {
|
||||
valuePosition = panelData.code.valuePosition
|
||||
}
|
||||
|
||||
printLabel(labelText, X_AXIS, PANEL_HEIGHT * labelPosition / 100 / heightFactor, '1')
|
||||
printLabel(value, X_AXIS, PANEL_HEIGHT * valuePosition / 100 / heightFactor, '0.50')
|
||||
printLabel(labelText, X_AXIS, PANEL_HEIGHT * labelPosition / 100 / heightFactor, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction)
|
||||
printLabel(value, X_AXIS, PANEL_HEIGHT * valuePosition / 100 / heightFactor, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction)
|
||||
}
|
||||
|
||||
function printLabel (labelToPrint, x, y, opacity) {
|
||||
let labelPoint
|
||||
let fontSize = 10
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.SECONDARY
|
||||
|
||||
let label = '' + labelToPrint
|
||||
|
||||
let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO
|
||||
|
||||
labelPoint = {
|
||||
x: x - xOffset,
|
||||
y: y
|
||||
}
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
labelPoint = thisObject.fitFunction(labelPoint)
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
function newPanelTabButton () {
|
||||
function newUpDownButton () {
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
@@ -16,13 +16,12 @@ function newPanelTabButton () {
|
||||
/* Cointainer stuff */
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.name = 'Panel Tab Button'
|
||||
thisObject.container.name = 'Up Down Button'
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isClickeable = true
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.frame.containerName = 'Panel Tab Button'
|
||||
thisObject.container.frame.containerName = 'Up Down Button'
|
||||
|
||||
/* Animation to hide the pannel */
|
||||
thisObject.status = 'up'
|
||||
let upPosition = {}
|
||||
let downPosition = {}
|
||||
@@ -45,12 +44,12 @@ function newPanelTabButton () {
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.frame.width = 10
|
||||
thisObject.container.frame.height = 10
|
||||
thisObject.container.frame.width = 12
|
||||
thisObject.container.frame.height = 12
|
||||
|
||||
var position = {
|
||||
x: thisObject.parentContainer.frame.width - 14,
|
||||
y: 1
|
||||
let position = {
|
||||
x: thisObject.container.frame.parentFrame.width * 5.75 / 8 - thisObject.container.frame.width / 2,
|
||||
y: 40 * 4 / 8 - thisObject.container.frame.height / 2
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
+6
-11
@@ -24,7 +24,6 @@ function newPlotter () {
|
||||
thisObject.container = container
|
||||
|
||||
let coordinateSystem
|
||||
let plotterModuleConfig
|
||||
let slotHeight = (canvas.chartingSpace.viewport.visibleArea.bottomRight.y - canvas.chartingSpace.viewport.visibleArea.topLeft.y) / 10 // This is the amount of slots available
|
||||
let mustRecalculateDataPoints = false
|
||||
let atMousePositionFillStyles = new Map()
|
||||
@@ -82,7 +81,6 @@ function newPlotter () {
|
||||
|
||||
finalizeCoordinateSystem()
|
||||
coordinateSystem = undefined
|
||||
plotterModuleConfig = undefined
|
||||
slotHeight = undefined
|
||||
mustRecalculateDataPoints = undefined
|
||||
atMousePositionFillStyles = undefined
|
||||
@@ -498,6 +496,10 @@ function newPlotter () {
|
||||
for (let i = 0; i < records.length; i++) {
|
||||
let record = records[i]
|
||||
|
||||
/*
|
||||
In the formulas to create plotters, we allos users to reference the previous record.
|
||||
To enable that we need to link all records to the previous one in this way.
|
||||
*/
|
||||
if (i == 0) {
|
||||
record.previous = record
|
||||
} else {
|
||||
@@ -555,7 +557,7 @@ function newPlotter () {
|
||||
if (logged === false) {
|
||||
logged = true
|
||||
}
|
||||
/* Only calculate the datapoints for this record, if we have not calculate it before. */
|
||||
/* It seems we need to calculate the data points this time. */
|
||||
for (let k = 0; k < productDefinition.referenceParent.shapes.chartPoints.length; k++) {
|
||||
let chartPoints = productDefinition.referenceParent.shapes.chartPoints[k]
|
||||
for (let j = 0; j < chartPoints.points.length; j++) {
|
||||
@@ -582,13 +584,6 @@ function newPlotter () {
|
||||
|
||||
/* Store the data point at the local map */
|
||||
dataPoints.set(point.id, dataPoint)
|
||||
|
||||
if (plotterModuleConfig !== undefined) {
|
||||
if (plotterModuleConfig.slot !== undefined) {
|
||||
/* We reset the y coordinate since it will be transformed with another coordinate system to fit into a slot. */
|
||||
dataPoint.y = (-1) * y * coordinateSystem.scale.y + (plotterModuleConfig.slot.number - 1) * slotHeight + canvas.chartingSpace.viewport.visibleArea.topLeft.y
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -769,7 +764,7 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
|
||||
if (coordinateSystem.autoMinYScale === true || coordinateSystem.autosMaxScale === true) {
|
||||
if (coordinateSystem.autoMinYScale === true || coordinateSystem.autoMinYScale === true) {
|
||||
mustRecalculateDataPoints = true
|
||||
} else {
|
||||
mustRecalculateDataPoints = false
|
||||
|
||||
@@ -14,6 +14,7 @@ function newRateScale () {
|
||||
onMouseOverSomeTimeMachineContainer: onMouseOverSomeTimeMachineContainer,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
drawBackground: drawBackground,
|
||||
drawForeground: drawForeground,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
@@ -56,6 +57,10 @@ function newRateScale () {
|
||||
|
||||
let scaleDisplayTimer = 0
|
||||
let autoScaleButton
|
||||
|
||||
let wheelDeltaDirection
|
||||
let wheelDeltaCounter = 0
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
@@ -134,6 +139,42 @@ function newRateScale () {
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
if (IS_MAC) {
|
||||
let sensitivity
|
||||
if (event.wheelDelta < 0) {
|
||||
if (event.shiftKey === true) {
|
||||
sensitivity = 20
|
||||
} else {
|
||||
sensitivity = 5
|
||||
}
|
||||
if (wheelDeltaDirection === -1) {
|
||||
wheelDeltaCounter++
|
||||
if (wheelDeltaCounter < sensitivity) {
|
||||
return
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
}
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
wheelDeltaDirection = -1
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (wheelDeltaDirection === 1) {
|
||||
wheelDeltaCounter++
|
||||
if (wheelDeltaCounter < sensitivity) {
|
||||
return
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
}
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
wheelDeltaDirection = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.shiftKey === true) {
|
||||
autoScaleButton.container.eventHandler.raiseEvent('onMouseWheel', event)
|
||||
return
|
||||
@@ -391,13 +432,54 @@ function newRateScale () {
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground () {
|
||||
drawScale()
|
||||
}
|
||||
|
||||
function drawScale () {
|
||||
const SEPARATION = 50
|
||||
const NUMBER_OF_LABELS = Math.trunc(canvas.chartingSpace.viewport.height / SEPARATION)
|
||||
const FONT_SIZE = 15
|
||||
|
||||
for (let i = 0; i <= NUMBER_OF_LABELS; i++) {
|
||||
let ratePoint1 = {
|
||||
x: 0,
|
||||
y: TOP_SPACE_HEIGHT + SEPARATION * (i + 1)
|
||||
}
|
||||
let ratePoint2 = {
|
||||
x: 0,
|
||||
y: TOP_SPACE_HEIGHT + SEPARATION * (i + 0)
|
||||
}
|
||||
|
||||
let rate = getRateFromPointAtBrowserCanvas(ratePoint1, rateCalculationsContainer, coordinateSystem)
|
||||
let labels = scaleLabels(rate)
|
||||
let decimalsDisplace = labels[1].length * FONT_SIZE * FONT_ASPECT_RATIO
|
||||
|
||||
let fitPoint1 = thisObject.fitFunction(ratePoint1)
|
||||
let fitPoint2 = thisObject.fitFunction(ratePoint2)
|
||||
|
||||
if (fitPoint1.y === ratePoint1.y && fitPoint2.y === ratePoint2.y) {
|
||||
drawLabel(labels[1], 1 / 2, 0, 0, 0, FONT_SIZE, thisObject.container, UI_COLOR.GREY, undefined, ratePoint1.y)
|
||||
drawLabel(labels[2], 1 / 2, 0, decimalsDisplace, -5, 9, thisObject.container, UI_COLOR.GREY, undefined, ratePoint1.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawScaleBox () {
|
||||
if (thisObject.rate === undefined) { return }
|
||||
if (thisObject.payload === undefined) { return }
|
||||
if (thisObject.payload.node === undefined) { return }
|
||||
|
||||
let rate = thisObject.rate
|
||||
let icon1 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
let icon2 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
let labels = scaleLabels(thisObject.rate)
|
||||
|
||||
drawScaleDisplay(labels[0], labels[1], labels[2], 0, 0, 0, icon1, icon2, thisObject.container, backgroundColor)
|
||||
}
|
||||
|
||||
function scaleLabels (rate) {
|
||||
if (rate < coordinateSystem.min.y) {
|
||||
rate = coordinateSystem.min.y
|
||||
}
|
||||
@@ -405,23 +487,23 @@ function newRateScale () {
|
||||
rate = coordinateSystem.max.y
|
||||
}
|
||||
|
||||
let label = (rate - Math.trunc(rate)).toFixed(2)
|
||||
let label = dynamicDecimals(rate)
|
||||
let labelArray = label.split('.')
|
||||
let label1 = thisObject.payload.node.payload.parentNode.name
|
||||
let label2 = (Math.trunc(rate)).toLocaleString()
|
||||
let label3 = labelArray[1]
|
||||
if (label3 === undefined) { label3 = '00' }
|
||||
|
||||
let icon1 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
let icon2 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
if (rate < 1) {
|
||||
label2 = label
|
||||
label3 = ''
|
||||
}
|
||||
|
||||
if (scaleDisplayTimer > 0) {
|
||||
label2 = (coordinateSystem.scale.y * 10000).toFixed(2)
|
||||
label3 = 'SCALE'
|
||||
}
|
||||
|
||||
drawScaleDisplay(label1, label2, label3, 0, 0, 0, icon1, icon2, thisObject.container, backgroundColor)
|
||||
return [label1, label2, label3]
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ function newTimeFrameScale () {
|
||||
payload: undefined,
|
||||
isVisible: true,
|
||||
layersOn: undefined,
|
||||
adjustTimeFrame: adjustTimeFrame,
|
||||
onMouseOverSomeTimeMachineContainer: onMouseOverSomeTimeMachineContainer,
|
||||
draw: draw,
|
||||
drawForeground: drawForeground,
|
||||
@@ -21,7 +22,7 @@ function newTimeFrameScale () {
|
||||
const TIME_PERIOD_DEFAULT_VALUE = 0
|
||||
const MIN_HEIGHT = 50
|
||||
|
||||
let previousIsVisible = true
|
||||
let displayingRealTimeFrame = true
|
||||
let greyOutCoverLayer = false
|
||||
let isMouseOver
|
||||
|
||||
@@ -44,6 +45,10 @@ function newTimeFrameScale () {
|
||||
}
|
||||
}
|
||||
setupContainer()
|
||||
|
||||
let wheelDeltaDirection
|
||||
let wheelDeltaCounter = 0
|
||||
|
||||
return thisObject
|
||||
|
||||
function setupContainer () {
|
||||
@@ -119,21 +124,28 @@ function newTimeFrameScale () {
|
||||
function physics () {
|
||||
readObjectState()
|
||||
positioningPhysics()
|
||||
zoomOutPhysics()
|
||||
}
|
||||
|
||||
function zoomOutPhysics () {
|
||||
if ((thisObject.isVisible === true && previousIsVisible === false) && (canvas.chartingSpace.viewport.zoomTargetLevel >= ZOOM_OUT_THRESHOLD_FOR_CHANGING_TIME_FRAME)) {
|
||||
function adjustTimeFrame (elementsPlotted) {
|
||||
const ELEMENTS_PLOTTED_THREASHOLD = 500
|
||||
if (
|
||||
canvas.chartingSpace.viewport.zoomTargetLevel >= ZOOM_OUT_THRESHOLD_FOR_CHANGING_TIME_FRAME &&
|
||||
displayingRealTimeFrame === false
|
||||
) {
|
||||
let event = {}
|
||||
event.timeFrame = thisObject.timeFrame
|
||||
thisObject.container.eventHandler.raiseEvent('Time Frame Value Changed', event)
|
||||
previousIsVisible = true
|
||||
displayingRealTimeFrame = true
|
||||
}
|
||||
if ((thisObject.isVisible === false && previousIsVisible === true) || (canvas.chartingSpace.viewport.zoomTargetLevel < ZOOM_OUT_THRESHOLD_FOR_CHANGING_TIME_FRAME)) {
|
||||
if (
|
||||
elementsPlotted > ELEMENTS_PLOTTED_THREASHOLD &&
|
||||
canvas.chartingSpace.viewport.zoomTargetLevel < ZOOM_OUT_THRESHOLD_FOR_CHANGING_TIME_FRAME &&
|
||||
displayingRealTimeFrame === true
|
||||
) {
|
||||
let event = {}
|
||||
event.timeFrame = ONE_DAY_IN_MILISECONDS
|
||||
thisObject.container.eventHandler.raiseEvent('Time Frame Value Changed', event)
|
||||
previousIsVisible = false
|
||||
displayingRealTimeFrame = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +253,43 @@ function newTimeFrameScale () {
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
delta = event.wheelDelta
|
||||
if (IS_MAC) {
|
||||
let sensitivity
|
||||
if (event.wheelDelta < 0) {
|
||||
if (event.shiftKey === true) {
|
||||
sensitivity = 20
|
||||
} else {
|
||||
sensitivity = 5
|
||||
}
|
||||
if (wheelDeltaDirection === -1) {
|
||||
wheelDeltaCounter++
|
||||
if (wheelDeltaCounter < sensitivity) {
|
||||
return
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
}
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
wheelDeltaDirection = -1
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (wheelDeltaDirection === 1) {
|
||||
wheelDeltaCounter++
|
||||
if (wheelDeltaCounter < sensitivity) {
|
||||
return
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
}
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
wheelDeltaDirection = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let delta = event.wheelDelta
|
||||
if (delta < 0) {
|
||||
timeFrameIndex--
|
||||
if (timeFrameIndex < 0) {
|
||||
|
||||
@@ -12,6 +12,7 @@ function newTimeScale () {
|
||||
onMouseOverSomeTimeMachineContainer: onMouseOverSomeTimeMachineContainer,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
drawBackground: drawBackground,
|
||||
drawForeground: drawForeground,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
@@ -48,6 +49,9 @@ function newTimeScale () {
|
||||
}
|
||||
}
|
||||
|
||||
let wheelDeltaDirection
|
||||
let wheelDeltaCounter = 0
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
@@ -116,6 +120,42 @@ function newTimeScale () {
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
if (IS_MAC) {
|
||||
let sensitivity
|
||||
if (event.wheelDelta < 0) {
|
||||
if (event.shiftKey === true) {
|
||||
sensitivity = 20
|
||||
} else {
|
||||
sensitivity = 5
|
||||
}
|
||||
if (wheelDeltaDirection === -1) {
|
||||
wheelDeltaCounter++
|
||||
if (wheelDeltaCounter < sensitivity) {
|
||||
return
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
}
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
wheelDeltaDirection = -1
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (wheelDeltaDirection === 1) {
|
||||
wheelDeltaCounter++
|
||||
if (wheelDeltaCounter < sensitivity) {
|
||||
return
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
}
|
||||
} else {
|
||||
wheelDeltaCounter = 0
|
||||
wheelDeltaDirection = 1
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.shiftKey === true) {
|
||||
autoScaleButton.container.eventHandler.raiseEvent('onMouseWheel', event)
|
||||
return
|
||||
@@ -251,6 +291,44 @@ function newTimeScale () {
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground () {
|
||||
drawScale()
|
||||
}
|
||||
|
||||
function drawScale () {
|
||||
const SEPARATION = 150
|
||||
const NUMBER_OF_LABELS = Math.trunc(canvas.chartingSpace.viewport.width / SEPARATION)
|
||||
const FONT_SIZE = 15
|
||||
|
||||
for (let i = 0; i <= NUMBER_OF_LABELS; i++) {
|
||||
let timePoint = {
|
||||
x: SEPARATION * (i + 1),
|
||||
y: 0
|
||||
}
|
||||
|
||||
let time = getDateFromPointAtBrowserCanvas(timePoint, limitingContainer, coordinateSystem)
|
||||
let labels = scaleLabels(time, true)
|
||||
let labelDisplace = labels[1].length * FONT_SIZE * FONT_ASPECT_RATIO
|
||||
|
||||
let timePoint1 = {
|
||||
x: SEPARATION * (i + 1) - labelDisplace,
|
||||
y: 0
|
||||
}
|
||||
let timePoint2 = {
|
||||
x: SEPARATION * (i + 1) + labelDisplace,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let fitPoint1 = thisObject.fitFunction(timePoint1)
|
||||
let fitPoint2 = thisObject.fitFunction(timePoint2)
|
||||
|
||||
if (fitPoint1.x === timePoint1.x && fitPoint2.x === timePoint2.x) {
|
||||
drawLabel(labels[1], 1 / 2, 0, 18, 17, FONT_SIZE, thisObject.container, UI_COLOR.GREY, timePoint1.x, undefined)
|
||||
drawLabel(labels[2], 1 / 2, 0, 18, 30, 12, thisObject.container, UI_COLOR.GREY, timePoint1.x, undefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
drawScaleBox()
|
||||
autoScaleButton.draw()
|
||||
@@ -269,17 +347,27 @@ function newTimeScale () {
|
||||
function drawScaleBox () {
|
||||
if (thisObject.date === undefined) { return }
|
||||
|
||||
let label = thisObject.date.toUTCString()
|
||||
let icon1 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
let icon2 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
let labels = scaleLabels(thisObject.date)
|
||||
|
||||
drawScaleDisplay(labels[0], labels[1], labels[2], 0, 0, 0, icon1, icon2, thisObject.container, backgroundColor)
|
||||
}
|
||||
|
||||
function scaleLabels (date, excludeYear) {
|
||||
let label = date.toUTCString()
|
||||
let labelArray = label.split(' ')
|
||||
let label1 = thisObject.payload.node.payload.parentNode.name
|
||||
let label2 = labelArray[1] + ' ' + labelArray[2] + ' ' + labelArray[3]
|
||||
let label3 = labelArray[4]
|
||||
|
||||
let icon1 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
let icon2 = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
if (excludeYear === true) {
|
||||
label2 = labelArray[1] + ' ' + labelArray[2]
|
||||
}
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
|
||||
drawScaleDisplay(label1, label2, label3, 0, 0, 0, icon1, icon2, thisObject.container, backgroundColor)
|
||||
return [label1, label2, label3]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,8 +332,8 @@ function newChartingSpace () {
|
||||
timeMachine.payload.uiObject.setValue('Loading...')
|
||||
|
||||
/* Setting up the new time machine. */
|
||||
timeMachine.container.frame.position.x = browserCanvas.width / 2 - TIME_MACHINE_WIDTH / 2
|
||||
timeMachine.container.frame.position.y = browserCanvas.height / 2 - TIME_MACHINE_HEIGHT / 2
|
||||
timeMachine.container.frame.position.x = browserCanvas.width / 2 - browserCanvas.width / TIME_MACHINE_WIDTH / 2
|
||||
timeMachine.container.frame.position.y = browserCanvas.height / 2 - (browserCanvas.height - TOP_SPACE_HEIGHT - COCKPIT_SPACE_HEIGHT) / TIME_MACHINE_HEIGHT / 2
|
||||
timeMachine.initialize(onTimeMachineInitialized)
|
||||
|
||||
function onTimeMachineInitialized () {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
status: 'BOTTOM',
|
||||
assetBalances: undefined,
|
||||
fullscreen: undefined,
|
||||
toTop: toTop,
|
||||
toBottom: toBottom,
|
||||
@@ -40,7 +39,6 @@
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.assetBalances = undefined
|
||||
thisObject.fullscreen = undefined
|
||||
}
|
||||
|
||||
@@ -65,9 +63,6 @@
|
||||
canvasBrowserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
|
||||
thisObject.assetBalances = newQuotedAssetalances()
|
||||
thisObject.assetBalances.initialize()
|
||||
|
||||
thisObject.fullscreen = newFullScreen()
|
||||
thisObject.fullscreen.container.connectToParent(thisObject.container)
|
||||
thisObject.fullscreen.initialize()
|
||||
@@ -185,7 +180,6 @@
|
||||
|
||||
drawBackground()
|
||||
|
||||
thisObject.assetBalances.draw()
|
||||
// thisObject.fullscreen.draw()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
function newDesignSpace () {
|
||||
const MODULE_NAME = 'Strategy Space'
|
||||
const MODULE_NAME = 'Designe Space'
|
||||
let thisObject = {
|
||||
sidePanel: undefined,
|
||||
container: undefined,
|
||||
@@ -274,7 +274,11 @@ function newDesignSpace () {
|
||||
'template-structure',
|
||||
'template-target',
|
||||
'delink',
|
||||
'detach'
|
||||
'detach',
|
||||
'help',
|
||||
'key-a',
|
||||
'key-m',
|
||||
'key-r'
|
||||
]
|
||||
|
||||
for (let i = 0; i < iconsNames.length; i++) {
|
||||
|
||||
@@ -11,6 +11,17 @@ function newFloatingSpace () {
|
||||
floatingLayer: undefined, // This is the array of floatingObjects being displayed
|
||||
uiObjectConstructor: undefined,
|
||||
container: undefined,
|
||||
inMapMode: false,
|
||||
drawReferenceLines: false,
|
||||
drawChainLines: true,
|
||||
toggleDrawChainLines: toggleDrawChainLines,
|
||||
toggleDrawReferenceLines: toggleDrawReferenceLines,
|
||||
toggleMapMode: toggleMapMode,
|
||||
enterMapMode: enterMapMode,
|
||||
exitMapMode: exitMapMode,
|
||||
transformPointToMap: transformPointToMap,
|
||||
transformRadiusToMap: transformRadiusToMap,
|
||||
transformImagesizeToMap: transformImagesizeToMap,
|
||||
oneScreenUp: oneScreenUp,
|
||||
oneScreenDown: oneScreenDown,
|
||||
oneScreenLeft: oneScreenLeft,
|
||||
@@ -34,6 +45,7 @@ function newFloatingSpace () {
|
||||
thisObject.container.isDraggeable = true
|
||||
thisObject.container.isWheelable = true
|
||||
thisObject.container.detectMouseOver = true
|
||||
thisObject.container.isClickeable = false
|
||||
thisObject.container.frame.radius = 0
|
||||
|
||||
let devicePixelRatio = window.devicePixelRatio
|
||||
@@ -47,12 +59,12 @@ function newFloatingSpace () {
|
||||
let visible = false
|
||||
|
||||
const PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT = 25
|
||||
let eventSubscriptionId
|
||||
let onDragStartedEventSubscriptionId
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(eventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onDragStartedEventSubscriptionId)
|
||||
|
||||
thisObject.floatingLayer.finalize()
|
||||
thisObject.uiObjectConstructor.finalize()
|
||||
@@ -70,12 +82,111 @@ function newFloatingSpace () {
|
||||
thisObject.uiObjectConstructor = newUiObjectConstructor()
|
||||
thisObject.uiObjectConstructor.initialize(thisObject.floatingLayer)
|
||||
|
||||
eventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
onDragStartedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDragStarted', onDragStarted)
|
||||
}
|
||||
|
||||
function toggleDrawReferenceLines () {
|
||||
if (thisObject.drawReferenceLines === true) {
|
||||
thisObject.drawReferenceLines = false
|
||||
} else {
|
||||
thisObject.drawReferenceLines = true
|
||||
}
|
||||
}
|
||||
|
||||
function toggleDrawChainLines () {
|
||||
if (thisObject.drawChainLines === true) {
|
||||
thisObject.drawChainLines = false
|
||||
} else {
|
||||
thisObject.drawChainLines = true
|
||||
}
|
||||
}
|
||||
|
||||
function transformPointToMap (point) {
|
||||
let returnPoint = {
|
||||
x: point.x - thisObject.container.frame.position.x,
|
||||
y: point.y - thisObject.container.frame.position.y
|
||||
}
|
||||
returnPoint.x = returnPoint.x / SPACE_SIZE * browserCanvas.width
|
||||
returnPoint.y = returnPoint.y / SPACE_SIZE * browserCanvas.height
|
||||
return returnPoint
|
||||
}
|
||||
|
||||
function transformRadiusToMap (radius) {
|
||||
const RADIUS_REDUCTION_FACTOR = 2
|
||||
return radius / RADIUS_REDUCTION_FACTOR
|
||||
}
|
||||
|
||||
function transformImagesizeToMap (imageSize) {
|
||||
const IMAGE_REDUCTION_FACTOR = 3
|
||||
return imageSize / IMAGE_REDUCTION_FACTOR
|
||||
}
|
||||
|
||||
function enterMapMode () {
|
||||
thisObject.inMapMode = true
|
||||
}
|
||||
|
||||
function exitMapMode () {
|
||||
thisObject.inMapMode = false
|
||||
}
|
||||
|
||||
function toggleMapMode () {
|
||||
if (thisObject.inMapMode === false) {
|
||||
enterMapMode()
|
||||
} else {
|
||||
exitMapMode()
|
||||
}
|
||||
}
|
||||
|
||||
function onDragStarted (event) {
|
||||
if (thisObject.inMapMode === false) {
|
||||
if (event.buttons !== 2) { return }
|
||||
event.candelDragging = true
|
||||
enterMapMode()
|
||||
} else {
|
||||
if (event.buttons !== 1) {
|
||||
event.candelDragging = true
|
||||
return
|
||||
}
|
||||
|
||||
let mousePosition = {
|
||||
x: event.x,
|
||||
y: event.y
|
||||
}
|
||||
|
||||
let mouseAtSpace = {
|
||||
x: mousePosition.x / browserCanvas.width * SPACE_SIZE,
|
||||
y: mousePosition.y / browserCanvas.height * SPACE_SIZE
|
||||
}
|
||||
/* Let's see if we can snap to some of the root nodes that are isHierarchyHead */
|
||||
let snapCandidateNodes = canvas.designSpace.workspace.getHierarchyHeads()
|
||||
for (let i = 0; i < snapCandidateNodes.length; i++) {
|
||||
let node = snapCandidateNodes[i]
|
||||
let nodePosition = {
|
||||
x: node.payload.floatingObject.container.frame.position.x,
|
||||
y: node.payload.floatingObject.container.frame.position.y
|
||||
}
|
||||
// nodePosition = node.payload.floatingObject.container.frame.frameThisPoint(nodePosition)
|
||||
|
||||
let distance = Math.sqrt(Math.pow(mouseAtSpace.x - nodePosition.x, 2) + Math.pow(mouseAtSpace.y - nodePosition.y, 2))
|
||||
const SNAP_THREASHOLD = 1000
|
||||
if (distance < SNAP_THREASHOLD) {
|
||||
mousePosition.x = nodePosition.x / SPACE_SIZE * browserCanvas.width
|
||||
mousePosition.y = nodePosition.y / SPACE_SIZE * browserCanvas.height
|
||||
}
|
||||
}
|
||||
|
||||
/* Movign the Floating Space to where the mouse is. */
|
||||
thisObject.container.frame.position.x = -mousePosition.x / browserCanvas.width * SPACE_SIZE + browserCanvas.width / 2
|
||||
thisObject.container.frame.position.y = -mousePosition.y / browserCanvas.height * SPACE_SIZE + browserCanvas.height / 2
|
||||
|
||||
exitMapMode()
|
||||
}
|
||||
}
|
||||
|
||||
function isItFar (payload, dontCheckParent) {
|
||||
/* If for any reason the paylaod is undefined we return false */
|
||||
if (payload === undefined) { return false }
|
||||
if (thisObject.inMapMode === true) { return false }
|
||||
|
||||
let radarFactor = 2 // How big is the margin
|
||||
|
||||
@@ -226,11 +337,6 @@ function newFloatingSpace () {
|
||||
return true
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
if (visible === false) { return }
|
||||
thisObject.floatingLayer.changeTargetRepulsion(event.wheelDelta)
|
||||
}
|
||||
|
||||
function makeVisible () {
|
||||
visible = true
|
||||
}
|
||||
|
||||
@@ -165,18 +165,34 @@ function newPanelsSpace () {
|
||||
let verticalLine = (canvas.chartingSpace.viewport.visibleArea.topRight.x - canvas.chartingSpace.viewport.visibleArea.topLeft.x) / 2 + canvas.chartingSpace.viewport.visibleArea.topLeft.x
|
||||
let horizontalLine = (canvas.chartingSpace.viewport.visibleArea.bottomRight.y - canvas.chartingSpace.viewport.visibleArea.topRight.y) / 2 + canvas.chartingSpace.viewport.visibleArea.topRight.y
|
||||
|
||||
if (panel.panelTabButton !== undefined) {
|
||||
if (panel.panelTabButton.status === 'up') {
|
||||
if (centerPoint.x < verticalLine) {
|
||||
panel.gravitatesTowards = 'topLeft'
|
||||
if (panel.upDownButton !== undefined) {
|
||||
if (panel.upDownButton.status === 'up') {
|
||||
if (panel.leftRightButton !== undefined) {
|
||||
if (panel.leftRightButton.status === 'left') {
|
||||
panel.gravitatesTowards = 'topLeft'
|
||||
} else {
|
||||
panel.gravitatesTowards = 'topRight'
|
||||
}
|
||||
} else {
|
||||
panel.gravitatesTowards = 'topRight'
|
||||
if (centerPoint.x < verticalLine) {
|
||||
panel.gravitatesTowards = 'topLeft'
|
||||
} else {
|
||||
panel.gravitatesTowards = 'topRight'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (centerPoint.x < verticalLine) {
|
||||
panel.gravitatesTowards = 'bottomLeft'
|
||||
if (panel.leftRightButton !== undefined) {
|
||||
if (panel.leftRightButton.status === 'left') {
|
||||
panel.gravitatesTowards = 'bottomLeft'
|
||||
} else {
|
||||
panel.gravitatesTowards = 'bottomRight'
|
||||
}
|
||||
} else {
|
||||
panel.gravitatesTowards = 'bottomRight'
|
||||
if (centerPoint.x < verticalLine) {
|
||||
panel.gravitatesTowards = 'bottomLeft'
|
||||
} else {
|
||||
panel.gravitatesTowards = 'bottomRight'
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -197,6 +213,10 @@ function newPanelsSpace () {
|
||||
/* According to the quadrant we push the panels to the sides */
|
||||
if (panel.gravitatesTowards === 'topLeft' || panel.gravitatesTowards === 'bottomLeft') {
|
||||
panel.container.frame.position.x = panel.container.frame.position.x - panel.container.speed.x
|
||||
if (panel.leftRightButton !== undefined) {
|
||||
if (panel.leftRightButton.status === 'left' || panel.leftRightButton.status === 'right') { // we avoid pushing other panels while in transition
|
||||
}
|
||||
}
|
||||
isOverlapping(i, panel.container)
|
||||
if (panel.container.frame.position.x < 0) {
|
||||
panel.container.frame.position.x = 0
|
||||
@@ -246,6 +266,11 @@ function newPanelsSpace () {
|
||||
|
||||
for (let i = 0; i < currentIndex; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
if (panel.leftRightButton !== undefined) {
|
||||
if (panel.leftRightButton.status !== 'left' && panel.leftRightButton.status !== 'right') { // we avoid pushing other panels while in transition
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (panel.isVisible === true && panel.isHidden === false) {
|
||||
if (isThisPointInsideThisFrame(corner1, panel.container.frame) === true) {
|
||||
pushOut(currentContainer, panel.container, panel.gravitatesTowards)
|
||||
|
||||
+50
-4
@@ -22,6 +22,22 @@ function drawContainerBackground (container, color, opacity, fitFunction) {
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
|
||||
function dynamicDecimals (value, minDecimals) {
|
||||
if (minDecimals === undefined) {
|
||||
minDecimals = 0
|
||||
}
|
||||
let decimals = 2
|
||||
if (value < 1) { decimals = 4 }
|
||||
if (Math.abs(Math.trunc(value * 100)) < 1) { decimals = 6 }
|
||||
if (Math.abs(Math.trunc(value * 10000)) < 1) { decimals = 8 }
|
||||
if (Math.abs(Math.trunc(value * 1000000)) < 1) { decimals = 10 }
|
||||
if (Math.abs(Math.trunc(value * 100000000)) < 1) { decimals = 12 }
|
||||
if (Math.abs(Math.trunc(value * 10000000000)) < 1) { value = 0; decimals = 0 }
|
||||
if (Math.trunc(value) === value) { decimals = minDecimals }
|
||||
let returnValue = Number(value).toFixed(decimals)
|
||||
return returnValue
|
||||
}
|
||||
|
||||
function savePropertyAtNodeConfig (payload, propertyName, value) {
|
||||
try {
|
||||
let code = JSON.parse(payload.node.code)
|
||||
@@ -194,7 +210,7 @@ function getMilisecondsFromPoint (point, container, coordinateSystem) {
|
||||
return point.x
|
||||
}
|
||||
|
||||
function moveToUserPosition (container, currentDate, currentRate, coordinateSystem, ignoreX, ignoreY, mousePosition) {
|
||||
function moveToUserPosition (container, currentDate, currentRate, coordinateSystem, ignoreX, ignoreY, mousePosition, fitFunction) {
|
||||
let targetPoint = {
|
||||
x: currentDate.valueOf(),
|
||||
y: currentRate
|
||||
@@ -228,15 +244,45 @@ function removeTime (datetime) {
|
||||
return dateOnly
|
||||
}
|
||||
|
||||
function printLabel (labelToPrint, x, y, opacity, fontSize, color) {
|
||||
function printLabel (labelToPrint, x, y, opacity, fontSize, color, center, container, fitFunction, noDecimals) {
|
||||
let labelPoint
|
||||
if (color === undefined) { color = UI_COLOR.DARK }
|
||||
if (fontSize === undefined) { fontSize = 10 };
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
let label = '' + labelToPrint
|
||||
let label = labelToPrint
|
||||
if (isNaN(label) === false && label !== '') {
|
||||
label = dynamicDecimals(labelToPrint)
|
||||
label = label.toLocaleString()
|
||||
if (noDecimals === true) {
|
||||
label = Math.trunc(label)
|
||||
}
|
||||
}
|
||||
|
||||
let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO
|
||||
|
||||
if (center === true) {
|
||||
labelPoint = {
|
||||
x: x - xOffset,
|
||||
y: y
|
||||
}
|
||||
} else {
|
||||
labelPoint = {
|
||||
x: x,
|
||||
y: y
|
||||
}
|
||||
}
|
||||
|
||||
if (container !== undefined) {
|
||||
labelPoint = container.frame.frameThisPoint(labelPoint)
|
||||
}
|
||||
|
||||
if (fitFunction !== undefined) {
|
||||
labelPoint = fitFunction(labelPoint)
|
||||
}
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + color + ', ' + opacity + ')'
|
||||
browserCanvasContext.fillText(label, x, y)
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
|
||||
function newUniqueId () {
|
||||
|
||||
@@ -105,8 +105,9 @@ function roundedCornersBackground (params) {
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
function drawLabel (label, xFactor, yFactor, xOffset, yOffset, fontSize, container) {
|
||||
function drawLabel (label, xFactor, yFactor, xOffset, yOffset, fontSize, container, fontColor, noFrameX, noFrameY) {
|
||||
if (label === undefined) { return }
|
||||
if (fontColor === undefined) { fontColor = UI_COLOR.WHITE }
|
||||
let fontOffset = label.length * fontSize * FONT_ASPECT_RATIO + 10
|
||||
|
||||
let labelPoint = {
|
||||
@@ -116,8 +117,16 @@ function drawLabel (label, xFactor, yFactor, xOffset, yOffset, fontSize, contain
|
||||
|
||||
labelPoint = container.frame.frameThisPoint(labelPoint)
|
||||
|
||||
if (noFrameX !== undefined) {
|
||||
labelPoint.x = noFrameX + xOffset
|
||||
}
|
||||
|
||||
if (noFrameY !== undefined) {
|
||||
labelPoint.y = noFrameY + yOffset
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
browserCanvasContext.fillStyle = 'rgba(' + fontColor + ', 1)'
|
||||
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
function newVideoRecorder () {
|
||||
let thisObject = {
|
||||
recordCanvas: recordCanvas
|
||||
recordCanvas: recordCanvas,
|
||||
physics: physics
|
||||
}
|
||||
let lastAction
|
||||
let wheelAnimationCounter = 0
|
||||
let lastWheelPointerIcon
|
||||
return thisObject
|
||||
|
||||
function physics () {
|
||||
wheelAnimationCounter--
|
||||
if (wheelAnimationCounter < 0) {
|
||||
wheelAnimationCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
function recordCanvas () {
|
||||
{
|
||||
const DISTANCE_BETWEEN_ICONS = 35
|
||||
@@ -33,16 +43,52 @@ function newVideoRecorder () {
|
||||
break
|
||||
}
|
||||
case 'wheel': {
|
||||
wheelAnimationCounter = 25
|
||||
if (canvas.mouse.event.delta > 0) {
|
||||
pointerIcon = canvas.designSpace.iconCollection.get('mouse-wheel-up')
|
||||
lastWheelPointerIcon = pointerIcon
|
||||
} else {
|
||||
pointerIcon = canvas.designSpace.iconCollection.get('mouse-wheel-down')
|
||||
lastWheelPointerIcon = pointerIcon
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
case 'key down': {
|
||||
pointerIcon = mousePointerIcon
|
||||
if (wheelAnimationCounter > 0) {
|
||||
pointerIcon = lastWheelPointerIcon
|
||||
} else {
|
||||
pointerIcon = mousePointerIcon
|
||||
}
|
||||
let key = canvas.mouse.event.key
|
||||
if (key === undefined) { break }
|
||||
switch (key.toLowerCase()) {
|
||||
case 'Escape':
|
||||
{
|
||||
pointerIcon = canvas.designSpace.iconCollection.get('key-m')
|
||||
break
|
||||
}
|
||||
case 'm':
|
||||
{
|
||||
pointerIcon = canvas.designSpace.iconCollection.get('key-m')
|
||||
break
|
||||
}
|
||||
case 'a':
|
||||
{
|
||||
pointerIcon = canvas.designSpace.iconCollection.get('key-a')
|
||||
break
|
||||
}
|
||||
case 'r':
|
||||
{
|
||||
pointerIcon = canvas.designSpace.iconCollection.get('key-r')
|
||||
break
|
||||
}
|
||||
case 'c':
|
||||
{
|
||||
pointerIcon = canvas.designSpace.iconCollection.get('key-r')
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'key up': {
|
||||
@@ -170,4 +216,3 @@ function newVideoRecorder () {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ function newFileCloud () {
|
||||
}
|
||||
|
||||
if (pMarket !== undefined) {
|
||||
fileName = fileName.replace('@BaseAsset', pMarket.baseAsset)
|
||||
fileName = fileName.replace('@QuotedAsset', pMarket.quotedAsset)
|
||||
filePath = filePath.replace('@BaseAsset', pMarket.baseAsset)
|
||||
filePath = filePath.replace('@QuotedAsset', pMarket.quotedAsset)
|
||||
}
|
||||
|
||||
if (pDataMine !== undefined) {
|
||||
@@ -99,7 +99,7 @@ function newFileCloud () {
|
||||
}
|
||||
|
||||
if (pExchange !== undefined) {
|
||||
filePath = filePath.replace('@Exchange', pExchange.code.codeName)
|
||||
filePath = filePath.replace('@Exchange', pExchange.name)
|
||||
}
|
||||
|
||||
filePath = filePath.replace('@Period', pPeriodName)
|
||||
|
||||
@@ -89,10 +89,10 @@ function newFileCursor () {
|
||||
beginDateRange = pBeginDateRange
|
||||
endDateRange = pEndDateRange
|
||||
|
||||
let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName
|
||||
let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
|
||||
systemEventHandler.listenToEvent(key, 'Dataset Updated', undefined, key + '-' + periodName, onResponseDataSet, updateFiles)
|
||||
|
||||
key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + pPeriodName
|
||||
key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
|
||||
systemEventHandler.listenToEvent(key, 'Data Range Updated', undefined, key, onResponseDataRange, updateDataRange)
|
||||
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
|
||||
@@ -74,7 +74,7 @@ function newFileSequence () {
|
||||
|
||||
callerId = newUniqueId()
|
||||
|
||||
let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName
|
||||
let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
|
||||
systemEventHandler.listenToEvent(key, 'Dataset Updated', undefined, callerId, onResponse, updateFiles)
|
||||
|
||||
function onResponse (message) {
|
||||
|
||||
@@ -36,13 +36,15 @@ function newMarketFiles () {
|
||||
let intervalHandle
|
||||
let finalized = false
|
||||
|
||||
let eventSubscriptionIdDatasetUpdated
|
||||
let eventSubscriptionIdDatasetUpdated = []
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
try {
|
||||
systemEventHandler.stopListening('Dataset Updated', eventSubscriptionIdDatasetUpdated)
|
||||
for (let i = 0; i < eventSubscriptionIdDatasetUpdated.length; i++) {
|
||||
systemEventHandler.stopListening('Dataset Updated', eventSubscriptionIdDatasetUpdated[i])
|
||||
}
|
||||
|
||||
thisObject.eventHandler.finalize()
|
||||
thisObject.eventHandler = undefined
|
||||
@@ -106,13 +108,13 @@ function newMarketFiles () {
|
||||
}
|
||||
|
||||
if (filesLoaded + filesNotLoaded === marketFilesPeriods.length) {
|
||||
let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName
|
||||
let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset
|
||||
systemEventHandler.listenToEvent(key, 'Dataset Updated', undefined, key + '-' + periodName, onResponse, updateFiles)
|
||||
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, thisObject)
|
||||
|
||||
function onResponse (message) {
|
||||
eventSubscriptionIdDatasetUpdated = message.eventSubscriptionId
|
||||
eventSubscriptionIdDatasetUpdated.push(message.eventSubscriptionId)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
exports.newCommons = function newCommons(bot, logger, UTILITIES) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
|
||||
const MODULE_NAME = "Commons";
|
||||
|
||||
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
|
||||
const GMT_SECONDS = ':00.000 GMT+0000';
|
||||
|
||||
let thisObject = {
|
||||
initializeStorage: initializeStorage
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initializeStorage(charlyStorage, bruceStorage, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initializeStorage -> Entering function."); }
|
||||
|
||||
initializeBruceStorage();
|
||||
|
||||
function initializeBruceStorage() {
|
||||
|
||||
bruceStorage.initialize(bot.dataMine, onBruceInizialized);
|
||||
|
||||
function onBruceInizialized(err) {
|
||||
|
||||
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
|
||||
|
||||
initializeCharlyStorage();
|
||||
|
||||
} else {
|
||||
logger.write(MODULE_NAME, "[ERROR] initializeStorage -> initializeBruceStorage -> onBruceInizialized -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initializeCharlyStorage() {
|
||||
|
||||
charlyStorage.initialize(bot.dataMine, onCharlyInizialized);
|
||||
|
||||
function onCharlyInizialized(err) {
|
||||
|
||||
if (err.result === global.DEFAULT_OK_RESPONSE.result) {
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
} else {
|
||||
logger.write(MODULE_NAME, "[ERROR] initializeStorage -> initializeCharlyStorage -> onCharlyInizialized -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] initializeStorage -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,813 +0,0 @@
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
|
||||
const GMT_SECONDS = ':00.000 GMT+0000';
|
||||
const GMT_MILI_SECONDS = '.000 GMT+0000';
|
||||
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
|
||||
|
||||
const MODULE_NAME = "User Bot";
|
||||
|
||||
const TRADES_FOLDER_NAME = "Trades";
|
||||
|
||||
const CANDLES_FOLDER_NAME = "Candles";
|
||||
const CANDLES_ONE_MIN = "One-Min";
|
||||
|
||||
const VOLUMES_FOLDER_NAME = "Volumes";
|
||||
const VOLUMES_ONE_MIN = "One-Min";
|
||||
|
||||
thisObject = {
|
||||
initialize: initialize,
|
||||
start: start
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
|
||||
let statusDependencies;
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize(pStatusDependencies, callBackFunction) {
|
||||
|
||||
statusDependencies = pStatusDependencies;
|
||||
|
||||
logger.fileName = MODULE_NAME
|
||||
logger.initialize();
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This process is going to do the following:
|
||||
Read the trades from Charly's Output and pack them into daily files with candles of one minute.
|
||||
*/
|
||||
|
||||
function start(callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
|
||||
|
||||
let processDate = new Date((new Date()).getUTCFullYear() + "-" + ((new Date()).getUTCMonth() + 1) + "-1 00:00:00.000 GMT+0000");
|
||||
|
||||
let thisDatetime = new Date();
|
||||
|
||||
let market = bot.market;
|
||||
|
||||
let lastTradeFileProcessed; // Datetime of the last file certified by the Hole Fixing process as without permanent holes.
|
||||
let firstTradeFile; // Datetime of the first trade file in the whole market history.
|
||||
let lastTradeFileSaved; // Datetime of the last verified file without holes.
|
||||
let lastCandleClose; // Value of the last candle close.
|
||||
let lastTradeFile; // Datetime pointing to the last Trade File sucessfuly processed and included in the last file.
|
||||
let beginingOfMarket
|
||||
|
||||
getContextVariables();
|
||||
|
||||
function getContextVariables() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Entering function."); }
|
||||
|
||||
let thisReport;
|
||||
let reportKey;
|
||||
|
||||
/* First Status Report */
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-Trades" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
if (statusDependencies.statusReports.get(reportKey).status === "Status Report is corrupt.") {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. ");
|
||||
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
|
||||
return;
|
||||
}
|
||||
|
||||
thisReport = statusDependencies.statusReports.get(reportKey).file;
|
||||
|
||||
if (thisReport.beginingOfMarket === undefined) {
|
||||
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> Undefined Last File. -> reportKey = " + reportKey);
|
||||
logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> It is too early too run this process since the trade history of the market is not there yet.");
|
||||
|
||||
let customOK = {
|
||||
result: global.CUSTOM_OK_RESPONSE.result,
|
||||
message: "Dependency does not exist."
|
||||
}
|
||||
logger.write(MODULE_NAME, "[WARN] start -> getContextVariables -> customOK = " + customOK.message);
|
||||
callBackFunction(customOK);
|
||||
return;
|
||||
}
|
||||
|
||||
firstTradeFile = new Date(thisReport.beginingOfMarket.year + "-" + thisReport.beginingOfMarket.month + "-" + thisReport.beginingOfMarket.days + " " + thisReport.beginingOfMarket.hours + ":" + thisReport.beginingOfMarket.minutes + GMT_SECONDS);
|
||||
lastTradeFileSaved = new Date(thisReport.lastFileSaved.year + "-" + thisReport.lastFileSaved.month + "-" + thisReport.lastFileSaved.days + " " + thisReport.lastFileSaved.hours + ":" + thisReport.lastFileSaved.minutes + GMT_SECONDS);
|
||||
|
||||
/* Final Status Report */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AABruce" + "-" + "Single-Period-Daily" + "-" + "dataSet.V1"
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
if (statusDependencies.statusReports.get(reportKey).status === "Status Report is corrupt.") {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> Can not continue because self dependecy Status Report is corrupt. Aborting Process.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
|
||||
thisReport = statusDependencies.statusReports.get(reportKey).file;
|
||||
|
||||
if (thisReport.lastFile === undefined) { // Means this is the first time ever this process runs.
|
||||
logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Process Running for the very first time. -> reportKey = " + reportKey);
|
||||
|
||||
lastCandleClose = 0;
|
||||
lastTradeFileProcessed = new Date(firstTradeFile.valueOf() - ONE_DAY_IN_MILISECONDS)
|
||||
beginingOfMarket = new Date(firstTradeFile.valueOf())
|
||||
|
||||
buildCandlesAndVolumes();
|
||||
|
||||
} else {
|
||||
logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Process Running not for the very first time. -> reportKey = " + reportKey);
|
||||
|
||||
lastTradeFileProcessed = new Date(thisReport.lastTradeFile.year + "-" + thisReport.lastTradeFile.month + "-" + thisReport.lastTradeFile.days + " " + "00:00" + GMT_SECONDS);
|
||||
lastCandleClose = thisReport.candleClose;
|
||||
beginingOfMarket = new Date(thisReport.beginingOfMarket.year + "-" + thisReport.beginingOfMarket.month + "-" + thisReport.beginingOfMarket.days + " " + thisReport.beginingOfMarket.hours + ":" + thisReport.beginingOfMarket.minutes + GMT_SECONDS);
|
||||
|
||||
if (beginingOfMarket.valueOf() !== firstTradeFile.valueOf()) { // Reset Mechanism for Begining of the Market
|
||||
logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> Reset Mechanism for Begining of the Market Activated. -> reportKey = " + reportKey);
|
||||
|
||||
beginingOfMarket = new Date(firstTradeFile.valueOf())
|
||||
lastTradeFileProcessed = new Date(firstTradeFile.valueOf() - ONE_DAY_IN_MILISECONDS)
|
||||
lastCandleClose = 0
|
||||
buildCandlesAndVolumes()
|
||||
return
|
||||
}
|
||||
|
||||
if (thisReport.fileComplete === true) {
|
||||
buildCandlesAndVolumes();
|
||||
} else {
|
||||
lastTradeFile = new Date(thisReport.lastTradeFile.year + "-" + thisReport.lastTradeFile.month + "-" + thisReport.lastTradeFile.days + " " + thisReport.lastTradeFile.hours + ":" + thisReport.lastTradeFile.minutes + GMT_SECONDS);
|
||||
findPreviousContent();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> getContextVariables -> err = " + err.stack);
|
||||
if (err.message === "Cannot read property 'file' of undefined") {
|
||||
logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Check the bot configuration to see if all of its statusDependencies declarations are correct. ");
|
||||
logger.write(MODULE_NAME, "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys));
|
||||
}
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function findPreviousContent() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> Entering function."); }
|
||||
|
||||
let previousCandles;
|
||||
let previousVolumes;
|
||||
|
||||
getCandles();
|
||||
|
||||
function getCandles() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getCandles -> Entering function."); }
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let dateForPath = lastTradeFileProcessed.getUTCFullYear() + '/' + utilities.pad(lastTradeFileProcessed.getUTCMonth() + 1, 2) + '/' + utilities.pad(lastTradeFileProcessed.getUTCDate(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + CANDLES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getCandles -> reading file at dateForPath = " + dateForPath);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
let candlesFile;
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getCandles -> onFileReceived -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getCandles -> onFileReceived -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOG_FILE_CONTENT === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getCandles -> onFileReceived -> text = " + text);
|
||||
}
|
||||
|
||||
candlesFile = JSON.parse(text);
|
||||
previousCandles = candlesFile;
|
||||
getVolumes();
|
||||
|
||||
} catch (err) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getCandles -> onFileReceived -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getCandles -> onFileReceived -> filePath = " + filePath);
|
||||
logger.write(MODULE_NAME, "[HINT] start -> findPreviousContent -> getCandles -> onFileReceived -> Empty or corrupt volume file found.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getCandles -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function getVolumes() {
|
||||
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getVolumes -> Entering function."); }
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let dateForPath = lastTradeFileProcessed.getUTCFullYear() + '/' + utilities.pad(lastTradeFileProcessed.getUTCMonth() + 1, 2) + '/' + utilities.pad(lastTradeFileProcessed.getUTCDate(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + '/' + VOLUMES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getVolumes -> reading file at dateForPath = " + dateForPath);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
let volumesFile;
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getVolumes -> onFileReceived -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getVolumes -> onFileReceived -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getVolumes -> onFileReceived -> text = " + text);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOG_FILE_CONTENT === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> getVolumes -> onFileReceived -> text = " + text);
|
||||
}
|
||||
|
||||
volumesFile = JSON.parse(text);
|
||||
previousVolumes = volumesFile;
|
||||
lastTradeFileProcessed = new Date(lastTradeFileProcessed.valueOf() - ONE_DAY_IN_MILISECONDS); // We know that after the next call a new day will be added.
|
||||
buildCandlesAndVolumes(previousCandles, previousVolumes);
|
||||
|
||||
} catch (err) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getVolumes -> onFileReceived -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getVolumes -> onFileReceived -> filePath = " + filePath);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getVolumes -> onFileReceived -> text = " + text);
|
||||
logger.write(MODULE_NAME, "[HINT] start -> findPreviousContent -> getVolumes -> onFileReceived -> Empty or corrupt volume file found.");
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> getVolumes -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> findPreviousContent -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function buildCandlesAndVolumes(previousCandles, previousVolumes) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> Entering function."); }
|
||||
|
||||
/*
|
||||
Here we are going to scan the trades files packing them in candles files every one day.
|
||||
We need for this the last close value, bacause all candles that are empty of trades at the begining, they need to
|
||||
have a valid open and close value. This was previously calculated before arriving to this function.
|
||||
*/
|
||||
|
||||
let canAddPrevious = true;
|
||||
|
||||
try {
|
||||
nextFile();
|
||||
|
||||
function nextFile() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> Entering function."); }
|
||||
|
||||
lastTradeFileProcessed = new Date(lastTradeFileProcessed.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
|
||||
let date = new Date(lastTradeFileProcessed.valueOf() - 60 * 1000);
|
||||
|
||||
if (date.valueOf() < firstTradeFile.valueOf()) { // At the special case where we are at the begining of the market, this might be true.
|
||||
date = new Date(firstTradeFile.valueOf() - 60 * 1000);
|
||||
}
|
||||
|
||||
if (lastTradeFile !== undefined) {
|
||||
date = new Date(lastTradeFile.valueOf());
|
||||
}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> date = " + date); }
|
||||
|
||||
let candles = [];
|
||||
let volumes = [];
|
||||
|
||||
if (previousCandles !== undefined && canAddPrevious === true) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> Adding Previous Candles. "); }
|
||||
|
||||
for (let i = 0; i < previousCandles.length; i++) {
|
||||
|
||||
let candle = {
|
||||
open: previousCandles[i][2],
|
||||
close: previousCandles[i][3],
|
||||
min: previousCandles[i][0],
|
||||
max: previousCandles[i][1],
|
||||
begin: previousCandles[i][4],
|
||||
end: previousCandles[i][5]
|
||||
};
|
||||
|
||||
candles.push(candle);
|
||||
}
|
||||
}
|
||||
|
||||
if (previousVolumes !== undefined && canAddPrevious === true) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> Adding Previous Volumes. "); }
|
||||
|
||||
for (let i = 0; i < previousVolumes.length; i++) {
|
||||
|
||||
let volume = {
|
||||
begin: previousVolumes[i][2],
|
||||
end: previousVolumes[i][3],
|
||||
buy: previousVolumes[i][0],
|
||||
sell: previousVolumes[i][1]
|
||||
};
|
||||
|
||||
volumes.push(volume);
|
||||
}
|
||||
}
|
||||
|
||||
canAddPrevious = false; // We add them only onece.
|
||||
|
||||
nextDate();
|
||||
|
||||
function nextDate() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> nextDate -> Entering function."); }
|
||||
|
||||
date = new Date(date.valueOf() + 60 * 1000);
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> nextDate -> date = " + date); }
|
||||
|
||||
/* Check if we are outside the current Day / File */
|
||||
|
||||
if (date.getUTCDate() !== lastTradeFileProcessed.getUTCDate()) {
|
||||
|
||||
writeFiles(lastTradeFileProcessed, candles, volumes, true, onFilesWritten);
|
||||
|
||||
return;
|
||||
|
||||
function onFilesWritten() {
|
||||
|
||||
nextFile();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we have past the most recent hole fixed file */
|
||||
|
||||
if (date.valueOf() > lastTradeFileSaved.valueOf()) {
|
||||
|
||||
writeFiles(lastTradeFileProcessed, candles, volumes, false, onFilesWritten);
|
||||
return;
|
||||
|
||||
function onFilesWritten() {
|
||||
|
||||
if (FULL_LOG === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> nextDate -> Head of the market reached for market " + market.baseAsset + '_' + market.quotedAsset + ".");
|
||||
}
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
readTrades();
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> nextDate -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function readTrades() {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> nextDate -> readTrades -> Entering function."); }
|
||||
|
||||
lastTradeFile = new Date(date.valueOf());
|
||||
|
||||
let dateForPath = date.getUTCFullYear() + '/' + utilities.pad(date.getUTCMonth() + 1, 2) + '/' + utilities.pad(date.getUTCDate(), 2) + '/' + utilities.pad(date.getUTCHours(), 2) + '/' + utilities.pad(date.getUTCMinutes(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
let filePathRoot = bot.dataMine + "/" + "AACharly" + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + TRADES_FOLDER_NAME + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> nextDate -> readTrades -> reading file at dateForPath = " + dateForPath);
|
||||
|
||||
function onFileReceived(err, text) {
|
||||
|
||||
let tradesFile;
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> text = " + text);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOG_FILE_CONTENT === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> text = " + text);
|
||||
}
|
||||
|
||||
let candle = {
|
||||
open: lastCandleClose,
|
||||
close: lastCandleClose,
|
||||
min: lastCandleClose,
|
||||
max: lastCandleClose,
|
||||
begin: date.valueOf(),
|
||||
end: date.valueOf() + 60 * 1000 - 1
|
||||
};
|
||||
|
||||
let volume = {
|
||||
begin: date.valueOf(),
|
||||
end: date.valueOf() + 60 * 1000 - 1,
|
||||
buy: 0,
|
||||
sell: 0
|
||||
};
|
||||
|
||||
tradesFile = JSON.parse(text);
|
||||
|
||||
let tradesCount = utilities.pad(tradesFile.length, 5);
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> " + tradesCount + " trades found at " + filePath + " for market " + market.baseAsset + '_' + market.quotedAsset + ". ");
|
||||
|
||||
if (tradesFile.length > 0) {
|
||||
|
||||
/* Candle open and close Calculations */
|
||||
|
||||
candle.open = tradesFile[0][2];
|
||||
candle.close = tradesFile[tradesFile.length - 1][2];
|
||||
lastCandleClose = candle.close;
|
||||
}
|
||||
|
||||
for (let i = 0; i < tradesFile.length; i++) {
|
||||
|
||||
let record = {
|
||||
side: tradesFile[i][1],
|
||||
price: tradesFile[i][2],
|
||||
amount: tradesFile[i][3]
|
||||
};
|
||||
|
||||
let trade = {
|
||||
type: record.side,
|
||||
rate: record.price,
|
||||
amountA: record.amount,
|
||||
amountB: record.amount * record.price
|
||||
};
|
||||
|
||||
/* Candle min and max Calculations */
|
||||
|
||||
if (trade.rate < candle.min) {
|
||||
candle.min = trade.rate;
|
||||
}
|
||||
|
||||
if (trade.rate > candle.max) {
|
||||
candle.max = trade.rate;
|
||||
}
|
||||
|
||||
/* Volume Calculations */
|
||||
|
||||
if (trade.type === "sell") {
|
||||
volume.sell = volume.sell + trade.amountA;
|
||||
} else {
|
||||
volume.buy = volume.buy + trade.amountA;
|
||||
}
|
||||
}
|
||||
|
||||
candles.push(candle);
|
||||
volumes.push(volume);
|
||||
nextDate();
|
||||
|
||||
} catch (err) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> filePath = " + filePath);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> text = " + text);
|
||||
logger.write(MODULE_NAME, "[HINT] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> onFileReceived -> Empty or corrupt volume file found.");
|
||||
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> readTrades -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> nextFile -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> buildCandlesAndVolumes -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function writeFiles(date, candles, volumes, isFileComplete, callBack) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> Entering function."); }
|
||||
|
||||
/*
|
||||
Here we will write the contents of the Candles and Volumens files. If the File is declared as complete, we will also write the status report.
|
||||
*/
|
||||
|
||||
try {
|
||||
|
||||
writeCandles();
|
||||
|
||||
function writeCandles() {
|
||||
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeCandles -> Entering function."); }
|
||||
|
||||
let separator = "";
|
||||
let fileRecordCounter = 0;
|
||||
|
||||
let fileContent = "";
|
||||
|
||||
for (i = 0; i < candles.length; i++) {
|
||||
|
||||
fileContent = fileContent + separator + '[' + candles[i].min + "," + candles[i].max + "," + candles[i].open + "," + candles[i].close + "," + candles[i].begin + "," + candles[i].end + "]";
|
||||
if (separator === "") { separator = ","; }
|
||||
fileRecordCounter++;
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let dateForPath = date.getUTCFullYear() + '/' + utilities.pad(date.getUTCMonth() + 1, 2) + '/' + utilities.pad(date.getUTCDate(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + CANDLES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeCandles -> writing file at dateForPath = " + dateForPath);
|
||||
|
||||
function onFileCreated(err) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeCandles -> onFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeCandles -> onFileCreated -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOG_FILE_CONTENT === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeCandles -> onFileCreated -> fileContent = " + fileContent);
|
||||
}
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeCandles -> onFileCreated -> Finished with File @ " + market.baseAsset + "_" + market.quotedAsset + ", " + fileRecordCounter + " records inserted into " + filePath + "/" + fileName + "");
|
||||
|
||||
writeVolumes();
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeCandles -> onFileCreated -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeCandles -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function writeVolumes() {
|
||||
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeVolumes -> Entering function."); }
|
||||
|
||||
let separator = "";
|
||||
let fileRecordCounter = 0;
|
||||
|
||||
let fileContent = "";
|
||||
|
||||
for (i = 0; i < volumes.length; i++) {
|
||||
|
||||
/* Validation trying to find a BUG that changes the dates of rubish data. */
|
||||
|
||||
if (volumes[i].begin < 1262304000000 | volumes[i].end < 1262304000000) { // If it is storing a number that represents a date before the year 2010...
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> Invalid Date trying to be recorded on output file. ");
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> volumes[i].begin = " + volumes[i].begin);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> volumes[i].end = " + volumes[i].end);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> i = " + i);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> volumes = " + JSON.stringify(volumes));
|
||||
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
|
||||
fileContent = fileContent + separator + '[' + volumes[i].buy + "," + volumes[i].sell + "," + volumes[i].begin + "," + volumes[i].end + "]";
|
||||
if (separator === "") { separator = ","; }
|
||||
fileRecordCounter++;
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let dateForPath = date.getUTCFullYear() + '/' + utilities.pad(date.getUTCMonth() + 1, 2) + '/' + utilities.pad(date.getUTCDate(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + '/' + VOLUMES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeVolumes -> writing file at dateForPath = " + dateForPath);
|
||||
|
||||
function onFileCreated(err) {
|
||||
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeVolumes -> onFileCreated -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> onFileCreated -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOG_FILE_CONTENT === true) {
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeVolumes -> onFileCreated -> fileContent = " + fileContent);
|
||||
}
|
||||
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeVolumes -> onFileCreated -> Finished with File @ " + market.baseAsset + "_" + market.quotedAsset + ", " + fileRecordCounter + " records inserted into " + filePath + "/" + fileName + "");
|
||||
|
||||
writeReport();
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> onFileCreated -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeVolumes -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function writeReport() {
|
||||
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeReport -> Entering function."); }
|
||||
|
||||
writeStatusReport(date, lastTradeFile, lastCandleClose, isFileComplete, false, onStatusReportWritten);
|
||||
|
||||
function onStatusReportWritten(err) {
|
||||
|
||||
try {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeFiles -> writeReport -> onStatusReportWritten -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> onStatusReportWritten -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callBack();
|
||||
return;
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeReport -> onStatusReportWritten -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> writeReport -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeFiles -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function writeStatusReport(lastFileDate, lastTradeFile, candleClose, isFileComplete, isMonthComplete, callBack) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> Entering function."); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> lastFileDate = " + lastFileDate); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> lastTradeFile = " + lastTradeFile); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> candleClose = " + candleClose); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> isFileComplete = " + isFileComplete); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> isMonthComplete = " + isMonthComplete); }
|
||||
|
||||
try {
|
||||
|
||||
if (lastTradeFile === undefined) {
|
||||
|
||||
/* At the begining of a new month, it can happen for reasons not 100% clear that this variable gets undifined.
|
||||
Probably it is because the instance that was waiting to execute in coma state, wakes up before than Charly
|
||||
writting the trades of this new month. Anyway, when this happens, a different path in code is taken and this
|
||||
variable gets undefined. A workaround for that without further investigation of the real cause of the problem
|
||||
is to RETRY the execution until the normal conditions arise and everything continues working well. That is what
|
||||
we are going to do for now. */
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[WARN] start -> writeStatusReport -> Cannot write the status report."); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[WARN] start -> writeStatusReport -> lastTradeFile = undefined."); }
|
||||
|
||||
callBackFunction(global.DEFAULT_RETRY_RESPONSE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + bot.process + "-" + bot.dataSetVersion
|
||||
let statusReport = statusDependencies.statusReports.get(key);
|
||||
|
||||
statusReport.file = {
|
||||
lastFile: {
|
||||
year: lastFileDate.getUTCFullYear(),
|
||||
month: (lastFileDate.getUTCMonth() + 1),
|
||||
days: lastFileDate.getUTCDate()
|
||||
},
|
||||
lastTradeFile: {
|
||||
year: lastTradeFile.getUTCFullYear(),
|
||||
month: (lastTradeFile.getUTCMonth() + 1),
|
||||
days: lastTradeFile.getUTCDate(),
|
||||
hours: lastTradeFile.getUTCHours(),
|
||||
minutes: lastTradeFile.getUTCMinutes()
|
||||
},
|
||||
beginingOfMarket: {
|
||||
year: beginingOfMarket.getUTCFullYear(),
|
||||
month: (beginingOfMarket.getUTCMonth() + 1),
|
||||
days: beginingOfMarket.getUTCDate(),
|
||||
hours: beginingOfMarket.getUTCHours(),
|
||||
minutes: beginingOfMarket.getUTCMinutes()
|
||||
},
|
||||
candleClose: candleClose,
|
||||
fileComplete: isFileComplete
|
||||
};
|
||||
|
||||
let fileContent = JSON.stringify(statusReport);
|
||||
|
||||
statusReport.save(onSaved);
|
||||
|
||||
function onSaved(err) {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeStatusReport -> onSaved -> Entering function."); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> onSaved -> err = " + err.stack);
|
||||
callBackFunction(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "AABruce",
|
||||
"version": "1.0.0",
|
||||
"description": "Processes that get the order books from Poloniex.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Luis-Fernando-Molina",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
{
|
||||
"displayName": "Bruce",
|
||||
"codeName": "AABruce",
|
||||
"type": "Indicator Bot",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"dataMine": "AAMasters",
|
||||
"profilePicture": "Bruce.png",
|
||||
"dataSetVersion": "dataSet.V1",
|
||||
"processes": [
|
||||
{
|
||||
"name": "Single-Period-Daily",
|
||||
"description": "Produces two data-sets with candles and volumes.",
|
||||
"startMode": {
|
||||
"allMonths": {
|
||||
"run": "true",
|
||||
"minYear": "2019",
|
||||
"maxYear": "2019"
|
||||
},
|
||||
"oneMonth": {
|
||||
"run": "false",
|
||||
"year": "2018",
|
||||
"month": "6"
|
||||
},
|
||||
"noTime": {
|
||||
"run": "false"
|
||||
},
|
||||
"fixedInterval": {
|
||||
"run": "false",
|
||||
"interval": 0
|
||||
}
|
||||
},
|
||||
"deadWaitTime": 0,
|
||||
"normalWaitTime": 0,
|
||||
"retryWaitTime": 10000,
|
||||
"sleepWaitTime": 3600000,
|
||||
"comaWaitTime": 86400000,
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
},
|
||||
"process": "Historic-Trades",
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
},
|
||||
"process": "Hole-Fixing",
|
||||
"dataSetVersion": "dataSet.V1",
|
||||
"dataSetSection": "Month",
|
||||
"waitUntilNextUpdate": true
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AABruce",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
},
|
||||
"process": "Single-Period-Daily",
|
||||
"dataSetVersion": "dataSet.V1",
|
||||
"dataSetSection": "Month"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"codeName": "Candles",
|
||||
"displayName": "Candles",
|
||||
"description": "01 Min Candles.",
|
||||
"storageAccount": "aamasters",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "One-Min",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "01-min" ],
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/One-Min",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
}
|
||||
],
|
||||
"exchangeList": [
|
||||
{
|
||||
"name": "Poloniex"
|
||||
},
|
||||
{
|
||||
"name": "Coss"
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"codeName": "PlottersCandlesVolumes",
|
||||
"moduleName": "Candles"
|
||||
}
|
||||
},
|
||||
{
|
||||
"codeName": "Volumes",
|
||||
"displayName": "Buy and Sell Volumes",
|
||||
"description": "01 Min Volumes.",
|
||||
"storageAccount": "aamasters",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "One-Min",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "01-min" ],
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/One-Min",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
}
|
||||
],
|
||||
"exchangeList": [
|
||||
{
|
||||
"name": "Poloniex"
|
||||
},
|
||||
{
|
||||
"name": "Coss"
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"codeName": "PlottersCandlesVolumes",
|
||||
"moduleName": "Volumes"
|
||||
}
|
||||
}
|
||||
],
|
||||
"storage": {
|
||||
"sas": "?sv=2017-07-29&ss=b&srt=sco&sp=rl&se=2018-12-31T22:59:59Z&st=2018-04-01T12:59:54Z&spr=https&sig=Fre%2FUWrF9IAXNnJSOZ%2F5q5LUow9uno7dXg5pGZ3YDzo%3D",
|
||||
"fileUri": "https://aamasters.blob.core.windows.net"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+30
-25
@@ -1,4 +1,4 @@
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const INTENSIVE_LOG = false;
|
||||
@@ -21,6 +21,7 @@
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
let statusDependencies;
|
||||
let beginingOfMarket
|
||||
@@ -50,7 +51,7 @@
|
||||
|
||||
This process is going to do the following:
|
||||
|
||||
Read the candles from Olivia and produce daily files with bollinger bands.
|
||||
Read the candles from Candles Volumes and produce daily files with bollinger bands.
|
||||
|
||||
*/
|
||||
|
||||
@@ -85,9 +86,9 @@
|
||||
let reportKey;
|
||||
let statusReport;
|
||||
|
||||
/* We look first for Charly in order to get when the market starts. */
|
||||
/* We look first for Exchange Raw Data in order to get when the market starts. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-Trades" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -121,9 +122,9 @@
|
||||
|
||||
contextVariables.firstTradeFile = new Date(thisReport.beginingOfMarket.year + "-" + thisReport.beginingOfMarket.month + "-" + thisReport.beginingOfMarket.days + " " + thisReport.beginingOfMarket.hours + ":" + thisReport.beginingOfMarket.minutes + GMT_SECONDS);
|
||||
|
||||
/* Second, we get the report from Olivia, to know when the marted ends. */
|
||||
/* Second, we get the report from Candles Volumes, to know when the marted ends. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -158,7 +159,7 @@
|
||||
|
||||
/* Finally we get our own Status Report. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AAChris" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Bollinger-Bands" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -246,6 +247,9 @@
|
||||
|
||||
let n;
|
||||
processDate = new Date(contextVariables.lastBandFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop.
|
||||
let fromDate = new Date(processDate.valueOf())
|
||||
let lastDate = new Date()
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildBands -> processDate = " + processDate); }
|
||||
|
||||
advanceTime();
|
||||
@@ -254,8 +258,6 @@
|
||||
|
||||
try {
|
||||
|
||||
logger.newInternalLoop(bot.codeName, bot.process);
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildBands -> advanceTime -> Entering function."); }
|
||||
|
||||
processDate = new Date(processDate.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
@@ -276,6 +278,15 @@
|
||||
|
||||
}
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let currentDateString = processDate.getUTCFullYear() + '-' + utilities.pad(processDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(processDate.getUTCDate(), 2);
|
||||
let currentDate = new Date(processDate)
|
||||
let percentage = global.getPercentage(fromDate, currentDate, lastDate)
|
||||
bot.processHeartBeat(currentDateString, percentage)
|
||||
|
||||
if (global.areEqualDates(currentDate, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, currentDate, percentage);
|
||||
}
|
||||
periodsLoop();
|
||||
|
||||
} catch (err) {
|
||||
@@ -328,9 +339,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildBands -> loopBody -> getPreviousDayFile -> Entering function."); }
|
||||
|
||||
let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -368,9 +378,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildBands -> loopBody -> getProcessDayFile -> Entering function."); }
|
||||
|
||||
let dateForPath = processDate.getUTCFullYear() + '/' + utilities.pad(processDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(processDate.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -598,10 +607,8 @@
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let dateForPath = processDate.getUTCFullYear() + '/' + utilities.pad(processDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(processDate.getUTCDate(), 2);
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + BOLLINGER_BANDS_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + BOLLINGER_BANDS_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -670,10 +677,8 @@
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let dateForPath = processDate.getUTCFullYear() + '/' + utilities.pad(processDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(processDate.getUTCDate(), 2);
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + PERCENTAGE_BANDWIDTH_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + PERCENTAGE_BANDWIDTH_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -826,7 +831,7 @@
|
||||
|
||||
let fileContent = JSON.stringify(dataRange);
|
||||
|
||||
let fileName = 'Data.Range.' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.Range.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + pProductFolder + "/" + bot.process;
|
||||
|
||||
filePath += '/' + fileName
|
||||
@@ -863,7 +868,7 @@
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = "AAMasters" + "-" + "AAChris" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
let reportKey = "Masters" + "-" + "Bollinger-Bands" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.processDatetime;
|
||||
+20
-13
@@ -1,4 +1,4 @@
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
@@ -17,6 +17,8 @@
|
||||
};
|
||||
|
||||
let statusDependencies;
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -43,7 +45,7 @@
|
||||
|
||||
This process is going to do the following:
|
||||
|
||||
Read the candles from Olivia and produce the bollinger bands out of them.
|
||||
Read the candles from Candles Volumes and produce the bollinger bands out of them.
|
||||
|
||||
*/
|
||||
|
||||
@@ -107,9 +109,9 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildBands -> loopBody -> nextCandleFile -> Entering function."); }
|
||||
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json";
|
||||
let fileName = "Data.json";
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -297,10 +299,8 @@
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + BOLLINGER_BANDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + BOLLINGER_BANDS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -369,10 +369,8 @@
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + PERCENTAGE_BANDWIDTH_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + PERCENTAGE_BANDWIDTH_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -467,12 +465,21 @@
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = "AAMasters" + "-" + "AAChris" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
let reportKey = "Masters" + "-" + "Bollinger-Bands" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.processDatetime;
|
||||
thisReport.save(callBack);
|
||||
|
||||
if (global.areEqualDates(bot.processDatetime, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, bot.processDatetime);
|
||||
}
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let currentDateString = bot.processDatetime.getUTCFullYear() + '-' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '-' + utilities.pad(bot.processDatetime.getUTCDate(), 2);
|
||||
let currentDate = new Date(bot.processDatetime)
|
||||
let lastDate = new Date()
|
||||
bot.processHeartBeat(currentDateString, global.getPercentage(currentDate, currentDate, lastDate))
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.stack);
|
||||
File renamed without changes.
+24
-24
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"displayName": "Chris",
|
||||
"codeName": "AAChris",
|
||||
"displayName": "Bollinger Bands",
|
||||
"codeName": "Bollinger-Bands",
|
||||
"type": "Indicator Bot",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"dataMine": "AAMasters",
|
||||
"profilePicture": "Chris.png",
|
||||
"dataMine": "Masters",
|
||||
"profilePicture": "Bollinger Bands.png",
|
||||
"dataSetVersion": "dataSet.V1",
|
||||
"processes": [
|
||||
{
|
||||
@@ -50,8 +50,8 @@
|
||||
],
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAChris",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Bollinger-Bands",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -60,8 +60,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAOlivia",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Candles-Volumes",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -111,8 +111,8 @@
|
||||
],
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -121,8 +121,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAOlivia",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Candles-Volumes",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -132,8 +132,8 @@
|
||||
"waitUntilNextUpdate": true
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAChris",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Bollinger-Bands",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -149,24 +149,24 @@
|
||||
"codeName": "Bollinger-Bands",
|
||||
"displayName": "Bollinger Bands",
|
||||
"description": "Bollinger Bands",
|
||||
"storageAccount": "aachris",
|
||||
"storageAccount": "Bollinger-Bands",
|
||||
"shareWith": "Public",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "Multi-Period-Market",
|
||||
"type": "Market Files",
|
||||
"validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs" ],
|
||||
"filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Market/@Period",
|
||||
"filePath": "Masters/Bollinger-Bands.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Market/@Period",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
},
|
||||
{
|
||||
"codeName": "Multi-Period-Daily",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ],
|
||||
"filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"filePath": "Masters/Bollinger-Bands.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"fileName": "@AssetA_@AssetB.json",
|
||||
"dataRange": {
|
||||
"filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Daily",
|
||||
"filePath": "Masters/Bollinger-Bands.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Daily",
|
||||
"fileName": "Data.Range.@AssetA_@AssetB.json"
|
||||
}
|
||||
}
|
||||
@@ -180,7 +180,7 @@
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"codeName": "PlottersBollingerBands",
|
||||
"moduleName": "BollingerBands"
|
||||
}
|
||||
@@ -189,24 +189,24 @@
|
||||
"codeName": "Percentage-Bandwidth",
|
||||
"displayName": "Percentage Bandwidth",
|
||||
"description": "Percentage Bandwidth",
|
||||
"storageAccount": "aachris",
|
||||
"storageAccount": "Bollinger-Bands",
|
||||
"shareWith": "Public",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "Multi-Period-Market",
|
||||
"type": "Market Files",
|
||||
"validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs" ],
|
||||
"filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Market/@Period",
|
||||
"filePath": "Masters/Bollinger-Bands.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Market/@Period",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
},
|
||||
{
|
||||
"codeName": "Multi-Period-Daily",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ],
|
||||
"filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"filePath": "Masters/Bollinger-Bands.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"fileName": "@AssetA_@AssetB.json",
|
||||
"dataRange": {
|
||||
"filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Daily",
|
||||
"filePath": "Masters/Bollinger-Bands.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Daily",
|
||||
"fileName": "Data.Range.@AssetA_@AssetB.json"
|
||||
}
|
||||
}
|
||||
@@ -220,7 +220,7 @@
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"codeName": "PlottersBollingerBands",
|
||||
"moduleName": "PercentageBandwidth"
|
||||
}
|
||||
+34
-16
@@ -1,4 +1,4 @@
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
@@ -23,6 +23,7 @@
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
let statusDependencies;
|
||||
let beginingOfMarket
|
||||
@@ -52,7 +53,7 @@
|
||||
|
||||
This process is going to do the following:
|
||||
|
||||
Read the candles and volumes from Charly and produce a file for each day and for each period with candles and volumes.
|
||||
Read the candles and volumes from Exchange Raw Data and produce a file for each day and for each period with candles and volumes.
|
||||
|
||||
*/
|
||||
|
||||
@@ -84,9 +85,9 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
let reportKey;
|
||||
let statusReport;
|
||||
|
||||
/* We look first for Charly in order to get when the market starts. */
|
||||
/* We look first for Exchange Raw Data in order to get when the market starts. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -120,9 +121,9 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
|
||||
contextVariables.firstTradeFile = new Date(thisReport.beginingOfMarket.year + "-" + thisReport.beginingOfMarket.month + "-" + thisReport.beginingOfMarket.days + " " + thisReport.beginingOfMarket.hours + ":" + thisReport.beginingOfMarket.minutes + GMT_SECONDS);
|
||||
|
||||
/* Second, we get the report from Charly, to know when the marted ends. */
|
||||
/* Second, we get the report from Exchange Raw Data, to know when the marted ends. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1"
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1"
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -157,7 +158,7 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
|
||||
/* Finally we get our own Status Report. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -228,7 +229,8 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
function buildCandles() {
|
||||
|
||||
try {
|
||||
|
||||
let fromDate = new Date(contextVariables.lastCandleFile.valueOf())
|
||||
let lastDate = new Date()
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandles -> Entering function."); }
|
||||
|
||||
let outputCandles;
|
||||
@@ -254,6 +256,15 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
return;
|
||||
}
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let currentDateString = contextVariables.lastCandleFile.getUTCFullYear() + '-' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '-' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let currentDate = new Date(contextVariables.lastCandleFile)
|
||||
let percentage = global.getPercentage(fromDate, currentDate, lastDate)
|
||||
bot.processHeartBeat(currentDateString, percentage)
|
||||
|
||||
if (global.areEqualDates(currentDate, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, currentDate, percentage);
|
||||
}
|
||||
/*
|
||||
|
||||
We prepere the arrays that will accumulate all the information for each output file.
|
||||
@@ -303,8 +314,8 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandles -> periodsLoop -> loopBody -> nextCandleFile -> Entering function."); }
|
||||
|
||||
let dateForPath = contextVariables.lastCandleFile.getUTCFullYear() + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
let filePathRoot = bot.dataMine + "/" + "AACharly" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Exchange-Raw-Data";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + CANDLES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -429,8 +440,8 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandles -> periodsLoop -> loopBody -> nextVolumeFile -> Entering function."); }
|
||||
|
||||
let dateForPath = contextVariables.lastCandleFile.getUTCFullYear() + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
let filePathRoot = bot.dataMine + "/" + "AACharly" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Exchange-Raw-Data";
|
||||
let filePath = filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + '/' + VOLUMES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -592,7 +603,7 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.json';
|
||||
let dateForPath = contextVariables.lastCandleFile.getUTCFullYear() + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
@@ -643,7 +654,7 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.json';
|
||||
let dateForPath = contextVariables.lastCandleFile.getUTCFullYear() + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
@@ -732,7 +743,7 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
|
||||
let fileContent = JSON.stringify(dataRange);
|
||||
|
||||
let fileName = 'Data.Range.' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.Range.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + pProductFolder + "/" + bot.process;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -752,6 +763,13 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Content written = " + fileContent);
|
||||
}
|
||||
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + pProductFolder + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let event = {
|
||||
dateRange: dataRange
|
||||
}
|
||||
|
||||
global.SYSTEM_EVENT_HANDLER.raiseEvent(key, 'Data Range Updated', event)
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -768,7 +786,7 @@ Read the candles and volumes from Charly and produce a file for each day and for
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
let reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.processDatetime;
|
||||
+39
-27
@@ -1,4 +1,4 @@
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
@@ -23,6 +23,7 @@
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
let statusDependencies;
|
||||
let beginingOfMarket
|
||||
@@ -50,16 +51,16 @@
|
||||
|
||||
This process is going to do the following:
|
||||
|
||||
Read the candles and volumes from Charly and produce a single Index File for Market Period. But this is the situation:
|
||||
Read the candles and volumes from Exchange Raw Data and produce a single Index File for Market Period. But this is the situation:
|
||||
|
||||
Charly has a dataset organized with daily files with candles of 1 min. Olivia is writting in this process a single file for each timeFrame for the whole market.
|
||||
Exchange Raw Data has a dataset organized with daily files with candles of 1 min. Candles Volumes is writting in this process a single file for each timeFrame for the whole market.
|
||||
Everytime this process run, must be able to resume its job and process everything pending until reaching the head of the market. So the tactic to do this is the
|
||||
following:
|
||||
|
||||
1. First we need to read the last file written by this process, and load all the information into in-memory arrays. We will then append to this arrays the new
|
||||
information we will get from Charly.
|
||||
information we will get from Exchange Raw Data.
|
||||
|
||||
2. We know from out status report which was the last DAY we processed from Charly, but we must be carefull, because that day mightn not have been complete, if the
|
||||
2. We know from out status report which was the last DAY we processed from Exchange Raw Data, but we must be carefull, because that day mightn not have been complete, if the
|
||||
last run found the head of the market. That means that we have to be carefull not to append candles that are already there. To simplify what we do is to discard
|
||||
all candles of the last processed day, and then we can process that full day again adding all the candles.
|
||||
|
||||
@@ -93,9 +94,9 @@
|
||||
let reportKey;
|
||||
let statusReport;
|
||||
|
||||
/* We look first for Charly in order to get when the market starts. */
|
||||
/* We look first for Exchange Raw Data in order to get when the market starts. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -129,9 +130,9 @@
|
||||
|
||||
contextVariables.firstTradeFile = new Date(thisReport.beginingOfMarket.year + "-" + thisReport.beginingOfMarket.month + "-" + thisReport.beginingOfMarket.days + " " + thisReport.beginingOfMarket.hours + ":" + thisReport.beginingOfMarket.minutes + GMT_SECONDS);
|
||||
|
||||
/* Second, we get the report from Charly, to know when the marted ends. */
|
||||
/* Second, we get the report from Exchange Raw Data, to know when the marted ends. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1"
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1"
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -166,7 +167,7 @@
|
||||
|
||||
/* Finally we get our own Status Report. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -269,7 +270,7 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> loopBody -> getCandles -> Entering function."); }
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + "/" + bot.process + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -308,7 +309,7 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> findPreviousContent -> loopBody -> getVolumes -> Entering function."); }
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + "/" + bot.process + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -377,6 +378,9 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandles -> Entering function."); }
|
||||
|
||||
let fromDate = new Date(contextVariables.lastCandleFile.valueOf())
|
||||
let lastDate = new Date()
|
||||
|
||||
/*
|
||||
Firstly we prepere the arrays that will accumulate all the information for each output file.
|
||||
*/
|
||||
@@ -403,9 +407,7 @@
|
||||
contextVariables.lastCandleFile = new Date(contextVariables.lastCandleFile.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandles -> advanceTime -> New processing time @ " + contextVariables.lastCandleFile.getUTCFullYear() + "/" + (contextVariables.lastCandleFile.getUTCMonth() + 1) + "/" + contextVariables.lastCandleFile.getUTCDate() + "."); }
|
||||
|
||||
logger.newInternalLoop(bot.codeName, bot.process, contextVariables.lastCandleFile);
|
||||
|
||||
|
||||
/* Validation that we are not going past the head of the market. */
|
||||
|
||||
if (contextVariables.lastCandleFile.valueOf() > contextVariables.maxCandleFile.valueOf()) {
|
||||
@@ -416,6 +418,16 @@
|
||||
return;
|
||||
}
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let currentDateString = contextVariables.lastCandleFile.getUTCFullYear() + '-' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '-' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let currentDate = new Date(contextVariables.lastCandleFile)
|
||||
let percentage = global.getPercentage(fromDate, currentDate, lastDate)
|
||||
bot.processHeartBeat(currentDateString, percentage)
|
||||
|
||||
if (global.areEqualDates(currentDate, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, currentDate, percentage);
|
||||
}
|
||||
|
||||
periodsLoop();
|
||||
|
||||
}
|
||||
@@ -452,12 +464,12 @@
|
||||
const timeFrame = global.marketFilesPeriods[n][1];
|
||||
|
||||
/*
|
||||
Here we are inside a Loop that is going to advance 1 day at the time, at each pass, will ready one of Charly's daily files and
|
||||
Here we are inside a Loop that is going to advance 1 day at the time, at each pass, will ready one of Exchange Raw Data's daily files and
|
||||
add all its candles to our in memory arrays. At the first iteration of this loop, we will add the candles that we are carrying
|
||||
from our previous run, the ones we already have in-memory. You can see below how we discard from those candles the ones that
|
||||
are belonging to the first day we are processing at this run, that it is exactly the same as the last day processed the privious
|
||||
run. By discarding these candles, we are ready to run after that standard function that will just add ALL the candles found each
|
||||
day at Charly.
|
||||
day at Exchange Raw Data.
|
||||
*/
|
||||
|
||||
if (previousCandles !== undefined) {
|
||||
@@ -507,7 +519,7 @@
|
||||
}
|
||||
|
||||
/*
|
||||
From here on is where every iteration of the loop fully runs. Here is where we read Charly's files and add their content to whatever
|
||||
From here on is where every iteration of the loop fully runs. Here is where we read Exchange Raw Data's files and add their content to whatever
|
||||
we already have in our arrays in-memory. In this way the process will run as many days needed and it should only stop when it reaches
|
||||
the head of the market.
|
||||
*/
|
||||
@@ -519,8 +531,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandles -> periodsLoop -> loopBody -> nextCandleFile -> Entering function."); }
|
||||
|
||||
let dateForPath = contextVariables.lastCandleFile.getUTCFullYear() + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
let filePathRoot = bot.dataMine + "/" + "AACharly" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Exchange-Raw-Data";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + CANDLES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -570,8 +582,8 @@
|
||||
let beginingOutputTime = contextVariables.lastCandleFile.valueOf();
|
||||
|
||||
/*
|
||||
The algorithm that follows is going to agregate candles of 1 min timeFrame read from Charly, into candles of each timeFrame
|
||||
that Olivia generates. For market files those timePediods goes from 1h to 24hs.
|
||||
The algorithm that follows is going to agregate candles of 1 min timeFrame read from Exchange Raw Data, into candles of each timeFrame
|
||||
that Candles Volumes generates. For market files those timePediods goes from 1h to 24hs.
|
||||
*/
|
||||
|
||||
for (let i = 0; i < totalOutputCandles; i++) {
|
||||
@@ -650,8 +662,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildCandles -> periodsLoop -> loopBody -> nextVolumeFile -> Entering function."); }
|
||||
|
||||
let dateForPath = contextVariables.lastCandleFile.getUTCFullYear() + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCMonth() + 1, 2) + '/' + utilities.pad(contextVariables.lastCandleFile.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
let filePathRoot = bot.dataMine + "/" + "AACharly" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Exchange-Raw-Data";
|
||||
let filePath = filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + '/' + VOLUMES_ONE_MIN + '/' + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -797,7 +809,7 @@
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + "/" + bot.process + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -847,7 +859,7 @@
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + "/" + bot.process + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -888,7 +900,7 @@
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
let reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.processDatetime;
|
||||
File renamed without changes.
+26
-26
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"displayName": "Olivia",
|
||||
"codeName": "AAOlivia",
|
||||
"displayName": "Candles Volumes",
|
||||
"codeName": "Candles-Volumes",
|
||||
"type": "Indicator Bot",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"dataMine": "AAMasters",
|
||||
"profilePicture": "Olivia.png",
|
||||
"dataMine": "Masters",
|
||||
"profilePicture": "Candles Volumes.png",
|
||||
"dataSetVersion": "dataSet.V1",
|
||||
"processes": [
|
||||
{
|
||||
@@ -50,8 +50,8 @@
|
||||
],
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -60,8 +60,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -72,8 +72,8 @@
|
||||
"waitUntilNextUpdate": true
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAOlivia",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Candles-Volumes",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -122,8 +122,8 @@
|
||||
],
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -132,8 +132,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -144,8 +144,8 @@
|
||||
"waitUntilNextUpdate": true
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAOlivia",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Candles-Volumes",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -161,24 +161,24 @@
|
||||
"codeName": "Candles",
|
||||
"displayName": "Candles",
|
||||
"description": "Two sets of files per period that contains candles.",
|
||||
"storageAccount": "aaolivia",
|
||||
"storageAccount": "Candles-Volumes",
|
||||
"shareWith": "Public",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "Multi-Period-Market",
|
||||
"type": "Market Files",
|
||||
"validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs" ],
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Market/@Period",
|
||||
"filePath": "Masters/Candles-Volumes.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Market/@Period",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
},
|
||||
{
|
||||
"codeName": "Multi-Period-Daily",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ],
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"filePath": "Masters/Candles-Volumes.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"fileName": "@AssetA_@AssetB.json",
|
||||
"dataRange": {
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Daily",
|
||||
"filePath": "Masters/Candles-Volumes.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Daily",
|
||||
"fileName": "Data.Range.@AssetA_@AssetB.json"
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"codeName": "PlottersCandlesVolumes",
|
||||
"moduleName": "Candles"
|
||||
}
|
||||
@@ -201,24 +201,24 @@
|
||||
"codeName": "Volumes",
|
||||
"displayName": "Buy and Sell Volumes",
|
||||
"description": "Two sets of files per period that contains buy and sell volumes.",
|
||||
"storageAccount": "aaolivia",
|
||||
"storageAccount": "Candles-Volumes",
|
||||
"shareWith": "Public",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "Multi-Period-Market",
|
||||
"type": "Market Files",
|
||||
"validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs" ],
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Market/@Period",
|
||||
"filePath": "Masters/Candles-Volumes.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Market/@Period",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
},
|
||||
{
|
||||
"codeName": "Multi-Period-Daily",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ],
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"filePath": "Masters/Candles-Volumes.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"fileName": "@AssetA_@AssetB.json",
|
||||
"dataRange": {
|
||||
"filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Daily",
|
||||
"filePath": "Masters/Candles-Volumes.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Daily",
|
||||
"fileName": "Data.Range.@AssetA_@AssetB.json"
|
||||
}
|
||||
}
|
||||
@@ -232,7 +232,7 @@
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"codeName": "PlottersCandlesVolumes",
|
||||
"moduleName": "Volumes"
|
||||
}
|
||||
File renamed without changes.
+180
-94
@@ -1,5 +1,5 @@
|
||||
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage, STATUS_REPORT, EXCHANGE_API) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE, STATUS_REPORT, EXCHANGE_API) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
@@ -15,15 +15,19 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger)
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
let statusDependencies
|
||||
|
||||
const ONE_MIN = 60000
|
||||
const ONE_DAY = ONE_MIN * 60 * 24
|
||||
|
||||
const MAX_OHLCVs_PER_EXECUTION = 500000
|
||||
const MAX_OHLCVs_PER_EXECUTION = 10000000
|
||||
const symbol = bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
const ccxt = require('ccxt')
|
||||
|
||||
let fetchType = "by Time"
|
||||
let lastId
|
||||
let firstId
|
||||
let allOHLCVs = []
|
||||
let thisReport;
|
||||
let since
|
||||
@@ -32,12 +36,13 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
let lastFile
|
||||
let exchangeId
|
||||
let options = {}
|
||||
let firstId
|
||||
let rateLimit = 500
|
||||
let exchange
|
||||
let uiStartDate = new Date(bot.uiStartDate)
|
||||
let fisrtTimeThisProcessRun = false
|
||||
let limit = 1000 // This is the default value
|
||||
let hostname
|
||||
let lastCandleOfTheDay
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -51,10 +56,10 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
|
||||
exchangeId = bot.exchange.toLowerCase()
|
||||
|
||||
/* Applying the parameters defined by the user at the Exchange node */
|
||||
/* Applying the parameters defined by the user at the Exchange Node Config */
|
||||
if (bot.exchangeNode.code.API !== undefined) {
|
||||
for (let i = 0; i < bot.exchangeNode.code.API.length; i++) {
|
||||
if (bot.exchangeNode.code.API[i].method === 'fetchOHLCVs') {
|
||||
if (bot.exchangeNode.code.API[i].method === 'fetch_ohlcv') {
|
||||
if (bot.exchangeNode.code.API[i].class !== undefined) {
|
||||
exchangeId = bot.exchangeNode.code.API[i].class
|
||||
}
|
||||
@@ -69,6 +74,12 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
if (bot.exchangeNode.code.API[i].rateLimit !== undefined) {
|
||||
rateLimit = bot.exchangeNode.code.API[i].rateLimit
|
||||
}
|
||||
if (bot.exchangeNode.code.API[i].hostname !== undefined) {
|
||||
hostname = bot.exchangeNode.code.API[i].hostname
|
||||
}
|
||||
if (bot.exchangeNode.code.API[i].fetchType !== undefined) {
|
||||
fetchType = bot.exchangeNode.code.API[i].fetchType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,6 +107,9 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
if (rateLimit !== undefined) {
|
||||
exchangeConstructorParams.rateLimit = rateLimit
|
||||
}
|
||||
if (hostname !== undefined) {
|
||||
exchangeConstructorParams.hostname = hostname
|
||||
}
|
||||
|
||||
exchange = new exchangeClass(exchangeConstructorParams)
|
||||
|
||||
@@ -110,22 +124,6 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
function start(callBackFunction) {
|
||||
try {
|
||||
|
||||
let lastCandle = {
|
||||
begin: 0,
|
||||
end: 0,
|
||||
open: 0,
|
||||
close: 0,
|
||||
min: 0,
|
||||
max: 0
|
||||
}
|
||||
|
||||
let lastVolume = {
|
||||
begin: 0,
|
||||
end: 0,
|
||||
buy: 0,
|
||||
sell: 0
|
||||
}
|
||||
|
||||
if (global.STOP_TASK_GRACEFULLY === true) {
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
return
|
||||
@@ -138,6 +136,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
|
||||
getContextVariables()
|
||||
if (abort === true) { return }
|
||||
await getFirstId()
|
||||
await getOHLCVs()
|
||||
if (abort === true) { return }
|
||||
if (global.STOP_TASK_GRACEFULLY === true) {
|
||||
@@ -152,7 +151,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
try {
|
||||
let reportKey;
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
if (statusDependencies.statusReports.get(reportKey).status === "Status Report is corrupt.") {
|
||||
@@ -166,6 +165,8 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
if (thisReport.file.beginingOfMarket !== undefined) { // This means this is not the first time this process run.
|
||||
beginingOfMarket = new Date(thisReport.file.beginingOfMarket.year + "-" + thisReport.file.beginingOfMarket.month + "-" + thisReport.file.beginingOfMarket.days + " " + thisReport.file.beginingOfMarket.hours + ":" + thisReport.file.beginingOfMarket.minutes + GMT_SECONDS);
|
||||
lastFile = new Date(thisReport.file.lastFile.year + "-" + thisReport.file.lastFile.month + "-" + thisReport.file.lastFile.days + " " + thisReport.file.lastFile.hours + ":" + thisReport.file.lastFile.minutes + GMT_SECONDS);
|
||||
lastId = thisReport.file.lastId
|
||||
lastCandleOfTheDay = thisReport.file.lastCandleOfTheDay
|
||||
} else { // This means this is the first time this process run.
|
||||
fisrtTimeThisProcessRun = true
|
||||
beginingOfMarket = new Date(uiStartDate.valueOf())
|
||||
@@ -206,20 +207,69 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
}
|
||||
}
|
||||
|
||||
async function getFirstId() {
|
||||
try {
|
||||
/* We need the first id only when we are going to fetch trades based on id and it is the first time the process runs*/
|
||||
if (fetchType !== "by Id") { return }
|
||||
if (lastId !== undefined) { return }
|
||||
lastId = 0
|
||||
|
||||
return
|
||||
/*
|
||||
const limit = 1
|
||||
const exchangeClass = ccxt[exchangeId]
|
||||
const exchange = new exchangeClass({
|
||||
'timeout': 30000,
|
||||
'enableRateLimit': true,
|
||||
verbose: false
|
||||
})
|
||||
|
||||
const OHLCVs = await exchange.fetchOHLCV(symbol, '1m', since, limit, undefined)
|
||||
|
||||
let lastRecord = OHLCVs[OHLCVs.length - 1]
|
||||
lastId = lastRecord.info[firstId]
|
||||
*/
|
||||
} catch (err) {
|
||||
/* If something fails trying to get an id close to since, we just will continue without an id.*/
|
||||
}
|
||||
}
|
||||
|
||||
async function getOHLCVs() {
|
||||
|
||||
try {
|
||||
let lastOHLCVKey = ''
|
||||
let params = undefined
|
||||
let previousSince
|
||||
let fromDate = new Date(since)
|
||||
let lastDate = new Date()
|
||||
|
||||
while (true) {
|
||||
|
||||
/* Reporting we are doing well */
|
||||
let processingDate = new Date(since)
|
||||
processingDate = processingDate.getUTCFullYear() + '-' + utilities.pad(processingDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(processingDate.getUTCDate(), 2);
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getOHLCVs -> Fetching OHLCVs @ " + processingDate + "-> exchange = " + bot.exchange + " -> symbol = " + symbol + " -> since = " + since + " -> limit = " + limit) }
|
||||
bot.processHeartBeat("Fetching " + allOHLCVs.length.toFixed(0) + " OHLCVs from " + bot.exchange + " " + symbol + " @ " + processingDate) // tell the world we are alive and doing well
|
||||
function heartBeat() {
|
||||
let processingDate = new Date(since)
|
||||
processingDate = processingDate.getUTCFullYear() + '-' + utilities.pad(processingDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(processingDate.getUTCDate(), 2);
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getOHLCVs -> Fetching OHLCVs @ " + processingDate + "-> exchange = " + bot.exchange + " -> symbol = " + symbol + " -> since = " + since + " -> limit = " + limit) }
|
||||
let heartBeatText = "Fetching " + allOHLCVs.length.toFixed(0) + " OHLCVs from " + bot.exchange + " " + symbol + " @ " + processingDate
|
||||
let currentDate = new Date(since)
|
||||
let percentage = global.getPercentage(fromDate, currentDate, lastDate)
|
||||
bot.processHeartBeat(heartBeatText, percentage) // tell the world we are alive and doing well
|
||||
if (global.areEqualDates(currentDate, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, currentDate, percentage);
|
||||
}
|
||||
}
|
||||
|
||||
heartBeat()
|
||||
|
||||
/* Defining if we will query the exchange by Date or Id */
|
||||
if (fetchType === "by Id") {
|
||||
/*
|
||||
params = {
|
||||
'fromId': lastId
|
||||
}
|
||||
*/
|
||||
since = lastId
|
||||
}
|
||||
|
||||
/* Fetching the OHLCVs from the exchange.*/
|
||||
await new Promise(resolve => setTimeout(resolve, rateLimit)) // rate limit
|
||||
@@ -253,7 +303,8 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
let OHLCV = OHLCVs[0]
|
||||
|
||||
initialProcessTimestamp = OHLCV[0] // 'timestamp'
|
||||
beginingOfMarket = new Date(Math.trunc (OHLCV[0] / ONE_DAY) * ONE_DAY) // 'timestamp'
|
||||
beginingOfMarket = new Date(Math.trunc(OHLCV[0] / ONE_DAY) * ONE_DAY) // 'timestamp'
|
||||
fromDate = new Date(beginingOfMarket.valueOf())
|
||||
fisrtTimeThisProcessRun = false
|
||||
}
|
||||
}
|
||||
@@ -264,6 +315,9 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
if (since === previousSince) {
|
||||
since++ // this prevents requesting in a loop OHLCVs with the same timestamp, that can happen when all the records fetched comes with exactly the same timestamp.
|
||||
}
|
||||
|
||||
|
||||
lastId = OHLCVs[OHLCVs.length - 1]['id']
|
||||
|
||||
for (let i = 0; i < OHLCVs.length; i++) {
|
||||
|
||||
@@ -276,9 +330,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
lastOHLCVKey = OHLCVKey
|
||||
}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getOHLCVs -> Fetching OHLCVs @ " + processingDate + "-> exchange = " + bot.exchange + " -> symbol = " + symbol + " -> since = " + since + " -> limit = " + limit) }
|
||||
bot.processHeartBeat("Fetching " + allOHLCVs.length.toFixed(0) + " OHLCVs from " + bot.exchange + " " + symbol + " @ " + processingDate) // tell the world we are alive and doing well
|
||||
|
||||
heartBeat()
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -313,8 +365,30 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
let error
|
||||
let separator
|
||||
let heartBeatCounter = 0
|
||||
let headOfTheMarketReached = false
|
||||
|
||||
let lastCandle = {
|
||||
begin: 0,
|
||||
end: 0,
|
||||
open: 0,
|
||||
close: 0,
|
||||
min: 0,
|
||||
max: 0
|
||||
}
|
||||
|
||||
let lastVolume = {
|
||||
begin: 0,
|
||||
end: 0,
|
||||
buy: 0,
|
||||
sell: 0
|
||||
}
|
||||
|
||||
let i = 0
|
||||
lastId = undefined
|
||||
|
||||
if (lastCandleOfTheDay !== undefined) {
|
||||
lastCandle = JSON.parse(JSON.stringify(lastCandleOfTheDay))
|
||||
}
|
||||
|
||||
controlLoop()
|
||||
|
||||
@@ -324,7 +398,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
let filesCreated = 0
|
||||
|
||||
/* Go through all possible 1 min candles of a day. */
|
||||
for (let j = 0; j < 60 * 24; j++) {
|
||||
for (let j = 0; j < 60 * 24; j++) {
|
||||
|
||||
let candle = {
|
||||
begin: currentDay * ONE_DAY + ONE_MIN * j,
|
||||
@@ -341,16 +415,43 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
sell: lastVolume.sell
|
||||
}
|
||||
|
||||
let record = allOHLCVs[i]
|
||||
let OHLCV = {
|
||||
timestamp: record[0],
|
||||
open: record[1],
|
||||
hight: record[2],
|
||||
low: record[3],
|
||||
close: record[4],
|
||||
volume: record[5]
|
||||
let processingDate = new Date(candle.begin)
|
||||
processingDate = processingDate.getUTCFullYear() + '-' + utilities.pad(processingDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(processingDate.getUTCDate(), 2);
|
||||
|
||||
if (candle.begin > (new Date()).valueOf()) {
|
||||
/* We stop when the current candle is pointing to a time in the future.*/
|
||||
headOfTheMarketReached = true
|
||||
saveFile(currentDay)
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> saveOHLCVs -> Saving OHLCVs @ " + processingDate + " -> i = " + i + " -> total = " + allOHLCVs.length) }
|
||||
bot.processHeartBeat("Saving " + i.toFixed(0) + " / " + allOHLCVs.length + " OHLCVs from " + bot.exchange + " " + symbol + " @ " + processingDate) // tell the world we are alive and doing well
|
||||
|
||||
/* We exit the loop and we aint comming back*/
|
||||
return
|
||||
}
|
||||
|
||||
let OHLCV = { // these values should be overrided unless there are no OHLVCs fetched from the exchange.
|
||||
timestamp: (new Date()).valueOf() + ONE_MIN,
|
||||
open: 0,
|
||||
hight: 0,
|
||||
low: 0,
|
||||
close: 0,
|
||||
volume: 0
|
||||
}
|
||||
|
||||
let record = allOHLCVs[i]
|
||||
|
||||
if (record !== undefined) { // can be undefined if there is no candle fetched from the exchange
|
||||
OHLCV = {
|
||||
timestamp: record[0],
|
||||
open: record[1],
|
||||
hight: record[2],
|
||||
low: record[3],
|
||||
close: record[4],
|
||||
volume: record[5]
|
||||
}
|
||||
}
|
||||
|
||||
let candleMinute = Math.trunc(candle.begin / ONE_MIN)
|
||||
let OHLCVMinute
|
||||
|
||||
@@ -365,6 +466,11 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
OHLCVMinute = Math.trunc(OHLCV.timestamp / ONE_MIN)
|
||||
|
||||
if (OHLCVMinute < candleMinute) {
|
||||
if (i >= allOHLCVs.length - 1) {
|
||||
/* We run out of OHLCVs, we can not move to the next OHLCV, we leave this function. */
|
||||
return
|
||||
}
|
||||
|
||||
i++
|
||||
record = allOHLCVs[i]
|
||||
OHLCV = {
|
||||
@@ -373,16 +479,15 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
hight: record[2],
|
||||
low: record[3],
|
||||
close: record[4],
|
||||
volume: record[5]
|
||||
volume: record[5],
|
||||
id: record[6]
|
||||
}
|
||||
checkOHLCVMinute()
|
||||
}
|
||||
}
|
||||
|
||||
/* Reporting we are doing well */
|
||||
let processingDate = new Date(candle.begin)
|
||||
processingDate = processingDate.getUTCFullYear() + '-' + utilities.pad(processingDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(processingDate.getUTCDate(), 2);
|
||||
heartBeatCounter--
|
||||
heartBeatCounter--
|
||||
if (heartBeatCounter <= 0) {
|
||||
heartBeatCounter = 1440
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> saveOHLCVs -> Saving OHLCVs @ " + processingDate + " -> i = " + i + " -> total = " + allOHLCVs.length) }
|
||||
@@ -397,7 +502,13 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
candle.max = OHLCV.hight
|
||||
volume.buy = OHLCV.volume / 2
|
||||
volume.sell = OHLCV.volume / 2
|
||||
i++
|
||||
|
||||
if (i < allOHLCVs.length - 1) {
|
||||
i++
|
||||
}
|
||||
|
||||
lastId = OHLCV.id
|
||||
|
||||
}
|
||||
lastCandle = candle
|
||||
|
||||
@@ -409,45 +520,29 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
}
|
||||
|
||||
/* Add the candle to the file content.*/
|
||||
|
||||
candlesFileContent = candlesFileContent + separator + '[' + candle.min + "," + candle.max + "," + candle.open + "," + candle.close + "," + candle.begin + "," + candle.end + "]";
|
||||
volumesFileContent = volumesFileContent + separator + '[' + volume.buy + "," + volume.sell + "," + volume.begin + "," + volume.end + "]";
|
||||
|
||||
if (i === allOHLCVs.length) {
|
||||
/* This was the last OHLCV, so we save the file.*/
|
||||
saveFile(currentDay)
|
||||
/* It might happen that there are several days after the last OHLCV without OHLCVs. We need to record empty files for them.*/
|
||||
if (allOHLCVs.length < MAX_OHLCVs_PER_EXECUTION) {
|
||||
let currentTimeDay = Math.trunc((new Date()).valueOf() / ONE_DAY)
|
||||
if (currentTimeDay - currentDay > 1) {
|
||||
createMissingEmptyFiles(currentDay, currentTimeDay)
|
||||
}
|
||||
}
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> saveOHLCVs -> Saving OHLCVs @ " + processingDate + " -> i = " + i + " -> total = " + allOHLCVs.length) }
|
||||
bot.processHeartBeat("Saving " + i.toFixed(0) + " / " + allOHLCVs.length + " OHLCVs from " + bot.exchange + " " + symbol + " @ " + processingDate) // tell the world we are alive and doing well
|
||||
|
||||
return
|
||||
/* We store the last candle of the day in order to have a previous candles during next execution. */
|
||||
if (j === 1440 - 1) {
|
||||
lastCandleOfTheDay = JSON.parse(JSON.stringify(candle))
|
||||
}
|
||||
}
|
||||
|
||||
previousDay = currentDay
|
||||
|
||||
if (i > 0) { // Only start saving at the day of the first candle.
|
||||
saveFile(currentDay)
|
||||
}
|
||||
|
||||
previousDay = currentDay
|
||||
if (error) {
|
||||
callBackFunction(error);
|
||||
return;
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
controlLoop()
|
||||
|
||||
function saveFile(day) {
|
||||
candlesFileContent = candlesFileContent + ']'
|
||||
volumesFileContent = volumesFileContent + ']'
|
||||
if (currentDay - previousDay > 1) {
|
||||
createMissingEmptyFiles(previousDay, currentDay)
|
||||
}
|
||||
let fileName = bot.market.baseAsset + '_' + bot.market.quotedAsset + '.json'
|
||||
|
||||
let fileName = 'Data.json'
|
||||
|
||||
filesToCreate++
|
||||
fileStorage.createTextFile(getFilePath(day * ONE_DAY, CANDLES_FOLDER_NAME) + '/' + fileName, candlesFileContent + '\n', onFileCreated);
|
||||
@@ -460,26 +555,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
needSeparator = false
|
||||
|
||||
}
|
||||
function createMissingEmptyFiles(begin, end) {
|
||||
|
||||
/*
|
||||
If this range is too wide, we will consider this means that the begin is before the begining of this market at this exchange.
|
||||
In that case we will change the begin and the beginingOfMarket
|
||||
*/
|
||||
|
||||
if ((end - begin) > 7) {
|
||||
begin = end
|
||||
beginingOfMarket = new Date(end * ONE_DAY)
|
||||
}
|
||||
|
||||
for (let j = begin + 1; j < end; j++) {
|
||||
let fileName = bot.market.baseAsset + '_' + bot.market.quotedAsset + '.json'
|
||||
filesToCreate++
|
||||
fileStorage.createTextFile(getFilePath(j * ONE_DAY, CANDLES_FOLDER_NAME) + '/' + fileName, "[]" + '\n', onFileCreated);
|
||||
filesToCreate++
|
||||
fileStorage.createTextFile(getFilePath(j * ONE_DAY, VOLUMES_FOLDER_NAME) + '/' + fileName, "[]" + '\n', onFileCreated);
|
||||
}
|
||||
}
|
||||
function onFileCreated(err) {
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> OHLCVsReadyToBeSaved -> onFileBCreated -> err = " + JSON.stringify(err));
|
||||
@@ -492,6 +568,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
controlLoop()
|
||||
}
|
||||
}
|
||||
|
||||
function getFilePath(timestamp, folderName) {
|
||||
let datetime = new Date(timestamp)
|
||||
let dateForPath = datetime.getUTCFullYear() + '/' +
|
||||
@@ -500,8 +577,6 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
let filePath = bot.filePathRoot + "/Output/" + folderName + '/' + dateForPath;
|
||||
return filePath
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function controlLoop() {
|
||||
@@ -510,8 +585,14 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
return
|
||||
}
|
||||
|
||||
if (error) {
|
||||
callBackFunction(error);
|
||||
return;
|
||||
}
|
||||
|
||||
currentDay++
|
||||
if (i < allOHLCVs.length) {
|
||||
|
||||
if (headOfTheMarketReached === false) {
|
||||
setImmediate(loop)
|
||||
} else {
|
||||
writeStatusReport()
|
||||
@@ -543,9 +624,14 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
hours: beginingOfMarket.getUTCHours(),
|
||||
minutes: beginingOfMarket.getUTCMinutes()
|
||||
},
|
||||
uiStartDate: uiStartDate.toUTCString()
|
||||
uiStartDate: uiStartDate.toUTCString(),
|
||||
lastCandleOfTheDay: lastCandleOfTheDay
|
||||
};
|
||||
|
||||
if (fetchType === "by Id") {
|
||||
thisReport.file.lastId = lastId
|
||||
}
|
||||
|
||||
thisReport.save(onSaved);
|
||||
|
||||
function onSaved(err) {
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage, STATUS_REPORT, EXCHANGE_API) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE, STATUS_REPORT, EXCHANGE_API) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
@@ -14,6 +14,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger)
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
let statusDependencies
|
||||
|
||||
const ONE_MINUTE = 60000
|
||||
@@ -135,7 +136,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
try {
|
||||
let reportKey;
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-Trades" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-Trades" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
if (statusDependencies.statusReports.get(reportKey).status === "Status Report is corrupt.") {
|
||||
@@ -376,7 +377,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
if (currentRecordMinute - previousRecordMinute > 1) {
|
||||
createMissingEmptyFiles(previousRecordMinute, currentRecordMinute)
|
||||
}
|
||||
let fileName = bot.market.baseAsset + '_' + bot.market.quotedAsset + '.json'
|
||||
let fileName = 'Data.json'
|
||||
if (previousRecordMinute >= initialProcessTimestamp / ONE_MINUTE) {
|
||||
filesToCreate++
|
||||
fileStorage.createTextFile(getFilePath(minute * ONE_MINUTE) + '/' + fileName, fileContent + '\n', onFileCreated);
|
||||
@@ -398,7 +399,7 @@ exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileSt
|
||||
}
|
||||
|
||||
for (let j = begin + 1; j < end; j++) {
|
||||
let fileName = bot.market.baseAsset + '_' + bot.market.quotedAsset + '.json'
|
||||
let fileName = 'Data.json'
|
||||
filesToCreate++
|
||||
fileStorage.createTextFile(getFilePath(j * ONE_MINUTE) + '/' + fileName, "[]" + '\n', onFileCreated);
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+18
-18
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"displayName": "Charly",
|
||||
"codeName": "AACharly",
|
||||
"displayName": "Exchange Raw Data",
|
||||
"codeName": "Exchange-Raw-Data",
|
||||
"type": "Sensor Bot",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"dataMine": "AAMasters",
|
||||
"profilePicture": "Charly.png",
|
||||
"dataMine": "Masters",
|
||||
"profilePicture": "Exchange Raw Data.png",
|
||||
"dataSetVersion": "dataSet.V1",
|
||||
"processes": [
|
||||
{
|
||||
@@ -40,8 +40,8 @@
|
||||
"comaWaitTime": 86400000,
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -80,8 +80,8 @@
|
||||
"comaWaitTime": 86400000,
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -90,8 +90,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -130,8 +130,8 @@
|
||||
"comaWaitTime": 86400000,
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -141,8 +141,8 @@
|
||||
"waitUntilNextUpdate": true
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -151,8 +151,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -162,8 +162,8 @@
|
||||
"dataSetSection": "Month"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
File renamed without changes.
+55
-48
@@ -1,4 +1,4 @@
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const INTENSIVE_LOG = false;
|
||||
@@ -24,6 +24,7 @@
|
||||
};
|
||||
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
let statusDependencies;
|
||||
let beginingOfMarket
|
||||
@@ -52,7 +53,7 @@
|
||||
|
||||
This process is going to do the following:
|
||||
|
||||
Read the candles and volumes from Olivia and produce for each market two files with candles stairs and volumes stairs respectively.
|
||||
Read the candles and volumes from Candles Volumes and produce for each market two files with candles stairs and volumes stairs respectively.
|
||||
|
||||
*/
|
||||
|
||||
@@ -92,9 +93,9 @@
|
||||
let reportKey;
|
||||
let statusReport;
|
||||
|
||||
/* We look first for Charly in order to get when the market starts. */
|
||||
/* We look first for Exchange Raw Data in order to get when the market starts. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AACharly" + "-" + "Historic-Trades" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Exchange-Raw-Data" + "-" + "Historic-OHLCVs" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -128,9 +129,9 @@
|
||||
|
||||
contextVariables.firstTradeFile = new Date(thisReport.beginingOfMarket.year + "-" + thisReport.beginingOfMarket.month + "-" + thisReport.beginingOfMarket.days + " " + thisReport.beginingOfMarket.hours + ":" + thisReport.beginingOfMarket.minutes + GMT_SECONDS);
|
||||
|
||||
/* Second, we get the report from Olivia, to know when the marted ends. */
|
||||
/* Second, we get the report from Candles Volumes, to know when the marted ends. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AAOlivia" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Candles-Volumes" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -165,7 +166,7 @@
|
||||
|
||||
/* Finally we get our own Status Report. */
|
||||
|
||||
reportKey = "AAMasters" + "-" + "AATom" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
reportKey = "Masters" + "-" + "Stairs-Patterns" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> getContextVariables -> reportKey = " + reportKey); }
|
||||
|
||||
statusReport = statusDependencies.statusReports.get(reportKey);
|
||||
@@ -254,6 +255,8 @@
|
||||
|
||||
let n;
|
||||
processDate = new Date(contextVariables.lastCandleFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop.
|
||||
let fromDate = new Date(processDate.valueOf())
|
||||
let lastDate = new Date()
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> processDate = " + processDate); }
|
||||
|
||||
advanceTime();
|
||||
@@ -262,8 +265,6 @@
|
||||
|
||||
try {
|
||||
|
||||
logger.newInternalLoop(bot.codeName, bot.process);
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> advanceTime -> Entering function."); }
|
||||
|
||||
processDate = new Date(processDate.valueOf() + ONE_DAY_IN_MILISECONDS);
|
||||
@@ -284,6 +285,16 @@
|
||||
|
||||
}
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let currentDateString = processDate.getUTCFullYear() + '-' + utilities.pad(processDate.getUTCMonth() + 1, 2) + '-' + utilities.pad(processDate.getUTCDate(), 2);
|
||||
let currentDate = new Date(processDate)
|
||||
let percentage = global.getPercentage(fromDate, currentDate, lastDate)
|
||||
bot.processHeartBeat(currentDateString, percentage)
|
||||
|
||||
if (global.areEqualDates(currentDate, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, currentDate, percentage);
|
||||
}
|
||||
|
||||
periodsLoop();
|
||||
|
||||
} catch (err) {
|
||||
@@ -353,10 +364,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> getEndOfLastCandleStair -> getCandleStairsFile -> Entering function."); }
|
||||
|
||||
let dateForPath = fileDate.getUTCFullYear() + '/' + utilities.pad(fileDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(fileDate.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + CANDLE_STAIRS_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
let fileName = "Data.json"
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLE_STAIRS_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
@@ -430,10 +439,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> getEndOfLastVolumeStair -> getCandleStairsFile -> Entering function."); }
|
||||
|
||||
let dateForPath = fileDate.getUTCFullYear() + '/' + utilities.pad(fileDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(fileDate.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + VOLUME_STAIRS_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
let fileName = "Data.json"
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUME_STAIRS_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.getTextFile(filePath, onFileReceived);
|
||||
@@ -533,9 +540,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> processCandles -> getCandleStairsFile -> Entering function."); }
|
||||
|
||||
let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -573,9 +579,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> processCandles -> getProcessDayFile -> Entering function."); }
|
||||
|
||||
let dateForPath = processDate.getUTCFullYear() + '/' + utilities.pad(processDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(processDate.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -653,9 +658,9 @@
|
||||
candle.begin = candlesFile[i][4];
|
||||
candle.end = candlesFile[i][5];
|
||||
|
||||
if (candle.open > candle.close) { candle.direction = 'down'; }
|
||||
if (candle.open < candle.close) { candle.direction = 'up'; }
|
||||
if (candle.open === candle.close) { candle.direction = 'side'; }
|
||||
if (candle.open > candle.close) { candle.direction = 'Down'; }
|
||||
if (candle.open < candle.close) { candle.direction = 'Up'; }
|
||||
if (candle.open === candle.close) { candle.direction = 'Side'; }
|
||||
|
||||
candles.push(candle);
|
||||
}
|
||||
@@ -689,7 +694,7 @@
|
||||
let currentCandle = candles[i];
|
||||
let nextCandle = candles[i + 1];
|
||||
|
||||
if (currentCandle.direction === nextCandle.direction && currentCandle.direction !== 'side') {
|
||||
if (currentCandle.direction === nextCandle.direction && currentCandle.direction !== 'Side') {
|
||||
|
||||
if (stairs === undefined) {
|
||||
|
||||
@@ -720,7 +725,7 @@
|
||||
if (currentCandle.min < nextCandle.min) { stairs.min = currentCandle.min; } else { stairs.min = nextCandle.min; }
|
||||
if (currentCandle.max > nextCandle.max) { stairs.max = currentCandle.max; } else { stairs.max = nextCandle.max; }
|
||||
|
||||
if (stairs.direction === 'up') {
|
||||
if (stairs.direction === 'Up') {
|
||||
|
||||
stairs.firstMin = currentCandle.open;
|
||||
stairs.firstMax = currentCandle.close;
|
||||
@@ -748,7 +753,7 @@
|
||||
if (stairs.min < nextCandle.min) { stairs.min = currentCandle.min; }
|
||||
if (stairs.max > nextCandle.max) { stairs.max = currentCandle.max; }
|
||||
|
||||
if (stairs.direction === 'up') {
|
||||
if (stairs.direction === 'Up') {
|
||||
|
||||
stairs.lastMin = nextCandle.open;
|
||||
stairs.lastMax = nextCandle.close;
|
||||
@@ -871,10 +876,9 @@
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let dateForPath = pDate.getUTCFullYear() + '/' + utilities.pad(pDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(pDate.getUTCDate(), 2);
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + CANDLE_STAIRS_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLE_STAIRS_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -947,9 +951,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> processVolumes -> getCandleStairsFile -> Entering function."); }
|
||||
|
||||
let dateForPath = previousDay.getUTCFullYear() + '/' + utilities.pad(previousDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(previousDay.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -987,9 +990,8 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> processVolumes -> getProcessDayFile -> Entering function."); }
|
||||
|
||||
let dateForPath = processDate.getUTCFullYear() + '/' + utilities.pad(processDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(processDate.getUTCDate(), 2);
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let fileName = "Data.json"
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + '/' + "Multi-Period-Daily" + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -1114,7 +1116,7 @@
|
||||
};
|
||||
|
||||
buyUpStairs.type = 'buy';
|
||||
buyUpStairs.direction = 'up';
|
||||
buyUpStairs.direction = 'Up';
|
||||
buyUpStairs.barsCount = 2;
|
||||
|
||||
buyUpStairs.begin = currentVolume.begin;
|
||||
@@ -1161,7 +1163,7 @@
|
||||
};
|
||||
|
||||
buyDownStairs.type = 'buy';
|
||||
buyDownStairs.direction = 'down';
|
||||
buyDownStairs.direction = 'Down';
|
||||
buyDownStairs.barsCount = 2;
|
||||
|
||||
buyDownStairs.begin = currentVolume.begin;
|
||||
@@ -1208,7 +1210,7 @@
|
||||
};
|
||||
|
||||
sellUpStairs.type = 'sell';
|
||||
sellUpStairs.direction = 'up';
|
||||
sellUpStairs.direction = 'Up';
|
||||
sellUpStairs.barsCount = 2;
|
||||
|
||||
sellUpStairs.begin = currentVolume.begin;
|
||||
@@ -1255,7 +1257,7 @@
|
||||
};
|
||||
|
||||
sellDownStairs.type = 'sell';
|
||||
sellDownStairs.direction = 'down';
|
||||
sellDownStairs.direction = 'Down';
|
||||
sellDownStairs.barsCount = 2;
|
||||
|
||||
sellDownStairs.begin = currentVolume.begin;
|
||||
@@ -1416,10 +1418,8 @@
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let dateForPath = pDate.getUTCFullYear() + '/' + utilities.pad(pDate.getUTCMonth() + 1, 2) + '/' + utilities.pad(pDate.getUTCDate(), 2);
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + VOLUME_STAIRS_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUME_STAIRS_FOLDER_NAME + "/" + bot.process + "/" + timeFrame + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -1581,7 +1581,7 @@
|
||||
|
||||
let fileContent = JSON.stringify(dataRange);
|
||||
|
||||
let fileName = 'Data.Range.' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
let fileName = 'Data.Range.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + pProductFolder + "/" + bot.process;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -1601,6 +1601,13 @@
|
||||
logger.write(MODULE_NAME, "[INFO] start -> writeDataRange -> onFileCreated -> Content written = " + fileContent);
|
||||
}
|
||||
|
||||
let key = bot.dataMine + "-" + bot.codeName + "-" + pProductFolder + "-" + bot.exchange + "-" + bot.market.baseAsset + '/' + bot.market.quotedAsset
|
||||
let event = {
|
||||
dateRange: dataRange
|
||||
}
|
||||
|
||||
global.SYSTEM_EVENT_HANDLER.raiseEvent(key, 'Data Range Updated', event)
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
}
|
||||
}
|
||||
@@ -1617,7 +1624,7 @@
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = "AAMasters" + "-" + "AATom" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
let reportKey = "Masters" + "-" + "Stairs-Patterns" + "-" + "Multi-Period-Daily" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.processDatetime;
|
||||
+32
-25
@@ -1,4 +1,4 @@
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, fileStorage) {
|
||||
exports.newUserBot = function newUserBot(bot, logger, COMMONS, UTILITIES, FILE_STORAGE) {
|
||||
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
@@ -23,6 +23,8 @@
|
||||
};
|
||||
|
||||
let statusDependencies;
|
||||
let utilities = UTILITIES.newCloudUtilities(bot, logger);
|
||||
let fileStorage = FILE_STORAGE.newFileStorage(logger);
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -48,7 +50,7 @@
|
||||
|
||||
This process is going to do the following:
|
||||
|
||||
Read the candles and volumes from Olivia and produce for each market two files with candles stairs and volumes stairs respectively.
|
||||
Read the candles and volumes from Candles Volumes and produce for each market two files with candles stairs and volumes stairs respectively.
|
||||
|
||||
*/
|
||||
|
||||
@@ -112,9 +114,9 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> nextCandleFile -> Entering function."); }
|
||||
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json";
|
||||
let fileName = "Data.json";
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + CANDLES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -169,9 +171,9 @@
|
||||
candle.begin = marketFile[i][4];
|
||||
candle.end = marketFile[i][5];
|
||||
|
||||
if (candle.open > candle.close) { candle.direction = 'down'; }
|
||||
if (candle.open < candle.close) { candle.direction = 'up'; }
|
||||
if (candle.open === candle.close) { candle.direction = 'side'; }
|
||||
if (candle.open > candle.close) { candle.direction = 'Down'; }
|
||||
if (candle.open < candle.close) { candle.direction = 'Up'; }
|
||||
if (candle.open === candle.close) { candle.direction = 'Side'; }
|
||||
|
||||
candles.push(candle);
|
||||
|
||||
@@ -201,7 +203,7 @@
|
||||
let currentCandle = candles[i];
|
||||
let nextCandle = candles[i + 1];
|
||||
|
||||
if (currentCandle.direction === nextCandle.direction && currentCandle.direction !== 'side') {
|
||||
if (currentCandle.direction === nextCandle.direction && currentCandle.direction !== 'Side') {
|
||||
|
||||
if (stairs === undefined) {
|
||||
|
||||
@@ -232,7 +234,7 @@
|
||||
if (currentCandle.min < nextCandle.min) { stairs.min = currentCandle.min; } else { stairs.min = nextCandle.min; }
|
||||
if (currentCandle.max > nextCandle.max) { stairs.max = currentCandle.max; } else { stairs.max = nextCandle.max; }
|
||||
|
||||
if (stairs.direction === 'up') {
|
||||
if (stairs.direction === 'Up') {
|
||||
|
||||
stairs.firstMin = currentCandle.open;
|
||||
stairs.firstMax = currentCandle.close;
|
||||
@@ -260,7 +262,7 @@
|
||||
if (stairs.min < nextCandle.min) { stairs.min = currentCandle.min; }
|
||||
if (stairs.max > nextCandle.max) { stairs.max = currentCandle.max; }
|
||||
|
||||
if (stairs.direction === 'up') {
|
||||
if (stairs.direction === 'Up') {
|
||||
|
||||
stairs.lastMin = nextCandle.open;
|
||||
stairs.lastMax = nextCandle.close;
|
||||
@@ -328,10 +330,8 @@
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + CANDLE_STAIRS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + CANDLE_STAIRS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -388,9 +388,9 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> buildStairs -> loopBody -> nextVolumeFile -> Entering function."); }
|
||||
|
||||
let fileName = market.baseAsset + '_' + market.quotedAsset + ".json"
|
||||
let fileName = "Data.json"
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + "AAOlivia" + "/" + bot.exchange;
|
||||
let filePathRoot = bot.exchange + "/" + bot.market.baseAsset + "-" + bot.market.quotedAsset + "/" + bot.dataMine + "/" + "Candles-Volumes";
|
||||
let filePath = filePathRoot + "/Output/" + VOLUMES_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
@@ -486,7 +486,7 @@
|
||||
};
|
||||
|
||||
buyUpStairs.type = 'buy';
|
||||
buyUpStairs.direction = 'up';
|
||||
buyUpStairs.direction = 'Up';
|
||||
buyUpStairs.barsCount = 2;
|
||||
|
||||
buyUpStairs.begin = currentVolume.begin;
|
||||
@@ -533,7 +533,7 @@
|
||||
};
|
||||
|
||||
buyDownStairs.type = 'buy';
|
||||
buyDownStairs.direction = 'down';
|
||||
buyDownStairs.direction = 'Down';
|
||||
buyDownStairs.barsCount = 2;
|
||||
|
||||
buyDownStairs.begin = currentVolume.begin;
|
||||
@@ -580,7 +580,7 @@
|
||||
};
|
||||
|
||||
sellUpStairs.type = 'sell';
|
||||
sellUpStairs.direction = 'up';
|
||||
sellUpStairs.direction = 'Up';
|
||||
sellUpStairs.barsCount = 2;
|
||||
|
||||
sellUpStairs.begin = currentVolume.begin;
|
||||
@@ -627,7 +627,7 @@
|
||||
};
|
||||
|
||||
sellDownStairs.type = 'sell';
|
||||
sellDownStairs.direction = 'down';
|
||||
sellDownStairs.direction = 'Down';
|
||||
sellDownStairs.barsCount = 2;
|
||||
|
||||
sellDownStairs.begin = currentVolume.begin;
|
||||
@@ -698,10 +698,8 @@
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
|
||||
let fileName = '' + market.baseAsset + '_' + market.quotedAsset + '.json';
|
||||
|
||||
let filePathRoot = bot.dataMine + "/" + bot.codeName + "/" + bot.exchange;
|
||||
let filePath = filePathRoot + "/Output/" + VOLUME_STAIRS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + VOLUME_STAIRS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrame;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -790,12 +788,21 @@
|
||||
|
||||
try {
|
||||
|
||||
let reportKey = "AAMasters" + "-" + "AATom" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
let reportKey = "Masters" + "-" + "Stairs-Patterns" + "-" + "Multi-Period-Market" + "-" + "dataSet.V1";
|
||||
let thisReport = statusDependencies.statusReports.get(reportKey);
|
||||
|
||||
thisReport.file.lastExecution = bot.processDatetime;
|
||||
thisReport.save(callBack);
|
||||
|
||||
if (global.areEqualDates(bot.processDatetime, new Date()) === false) {
|
||||
logger.newInternalLoop(bot.codeName, bot.process, bot.processDatetime);
|
||||
}
|
||||
|
||||
/* Telling the world we are alive and doing well */
|
||||
let currentDateString = bot.processDatetime.getUTCFullYear() + '-' + utilities.pad(bot.processDatetime.getUTCMonth() + 1, 2) + '-' + utilities.pad(bot.processDatetime.getUTCDate(), 2);
|
||||
let currentDate = new Date(bot.processDatetime)
|
||||
let lastDate = new Date()
|
||||
bot.processHeartBeat(currentDateString, global.getPercentage(currentDate, currentDate, lastDate))
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeStatusReport -> err = " + err.stack);
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "AAToma",
|
||||
"name": "Stairs-Patternsa",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
+24
-24
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"displayName": "Tom",
|
||||
"codeName": "AATom",
|
||||
"displayName": "Stairs Patterns",
|
||||
"codeName": "Stairs-Patterns",
|
||||
"type": "Indicator Bot",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"dataMine": "AAMasters",
|
||||
"profilePicture": "Tom.png",
|
||||
"dataMine": "Masters",
|
||||
"profilePicture": "Stairs Patterns.png",
|
||||
"dataSetVersion": "dataSet.V1",
|
||||
"processes": [
|
||||
{
|
||||
@@ -50,8 +50,8 @@
|
||||
],
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AATom",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Stairs-Patterns",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -60,8 +60,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAOlivia",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Candles-Volumes",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -111,8 +111,8 @@
|
||||
],
|
||||
"statusDependencies": [
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AACharly",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Exchange-Raw-Data",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -121,8 +121,8 @@
|
||||
"dataSetVersion": "dataSet.V1"
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AAOlivia",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Candles-Volumes",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -132,8 +132,8 @@
|
||||
"waitUntilNextUpdate": true
|
||||
},
|
||||
{
|
||||
"dataMine": "AAMasters",
|
||||
"bot": "AATom",
|
||||
"dataMine": "Masters",
|
||||
"bot": "Stairs-Patterns",
|
||||
"botVersion": {
|
||||
"major": 1,
|
||||
"minor": 0
|
||||
@@ -149,24 +149,24 @@
|
||||
"codeName": "Candle-Stairs",
|
||||
"displayName": "Candle-Stairs Patters",
|
||||
"description": "Two sets of files per period that contains candle-stairs patterns.",
|
||||
"storageAccount": "aatom",
|
||||
"storageAccount": "Stairs-Patterns",
|
||||
"shareWith": "Public",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "Multi-Period-Market",
|
||||
"type": "Market Files",
|
||||
"validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs" ],
|
||||
"filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Market/@Period",
|
||||
"filePath": "Masters/Stairs-Patterns.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Market/@Period",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
},
|
||||
{
|
||||
"codeName": "Multi-Period-Daily",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ],
|
||||
"filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"filePath": "Masters/Stairs-Patterns.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"fileName": "@AssetA_@AssetB.json",
|
||||
"dataRange": {
|
||||
"filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily",
|
||||
"filePath": "Masters/Stairs-Patterns.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily",
|
||||
"fileName": "Data.Range.@AssetA_@AssetB.json"
|
||||
}
|
||||
}
|
||||
@@ -180,7 +180,7 @@
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"codeName": "PlottersStairsPatterns",
|
||||
"moduleName": "CandleStairs"
|
||||
}
|
||||
@@ -189,24 +189,24 @@
|
||||
"codeName": "Volume-Stairs",
|
||||
"displayName": "Volume-Stairs Patters",
|
||||
"description": "Two sets of files per period that contains volume-stairs patterns.",
|
||||
"storageAccount": "aatom",
|
||||
"storageAccount": "Stairs-Patterns",
|
||||
"shareWith": "Public",
|
||||
"dataSets": [
|
||||
{
|
||||
"codeName": "Multi-Period-Market",
|
||||
"type": "Market Files",
|
||||
"validPeriods": [ "24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs" ],
|
||||
"filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Market/@Period",
|
||||
"filePath": "Masters/Stairs-Patterns.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Market/@Period",
|
||||
"fileName": "@AssetA_@AssetB.json"
|
||||
},
|
||||
{
|
||||
"codeName": "Multi-Period-Daily",
|
||||
"type": "Daily Files",
|
||||
"validPeriods": [ "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min" ],
|
||||
"filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"filePath": "Masters/Stairs-Patterns.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day",
|
||||
"fileName": "@AssetA_@AssetB.json",
|
||||
"dataRange": {
|
||||
"filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Daily",
|
||||
"filePath": "Masters/Stairs-Patterns.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Daily",
|
||||
"fileName": "Data.Range.@AssetA_@AssetB.json"
|
||||
}
|
||||
}
|
||||
@@ -220,7 +220,7 @@
|
||||
}
|
||||
],
|
||||
"plotter": {
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"codeName": "PlottersStairsPatterns",
|
||||
"moduleName": "VolumeStairs"
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersBollingerBandsBollingerBands() {
|
||||
function newMastersPlottersBollingerBandsBollingerBands() {
|
||||
|
||||
const MODULE_NAME = "Bands Plotter";
|
||||
const ERROR_LOG = true;
|
||||
+24
-55
@@ -1,5 +1,5 @@
|
||||
|
||||
function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel () {
|
||||
function newMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel () {
|
||||
|
||||
var thisObject = {
|
||||
fitFunction: undefined,
|
||||
@@ -17,7 +17,7 @@ function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel ()
|
||||
thisObject.container.frame.containerName = "Bollinger Band";
|
||||
|
||||
let currentBand;
|
||||
let panelTabButton
|
||||
let upDownButton
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -28,8 +28,8 @@ function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel ()
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentBand = undefined
|
||||
panelTabButton.finalize()
|
||||
panelTabButton = undefined
|
||||
upDownButton.finalize()
|
||||
upDownButton = undefined
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
@@ -40,18 +40,18 @@ function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel ()
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width * 3;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.bottomLeft.y - thisObject.container.frame.height;
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
panelTabButton.fitFunction = thisObject.fitFunction
|
||||
panelTabButton.initialize()
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container;
|
||||
|
||||
container = panelTabButton.getContainer(point)
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
@@ -83,7 +83,7 @@ function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel ()
|
||||
|
||||
plotCurrentBandInfo();
|
||||
|
||||
panelTabButton.draw()
|
||||
upDownButton.draw()
|
||||
}
|
||||
|
||||
|
||||
@@ -118,8 +118,6 @@ function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel ()
|
||||
y: Y_AXIS - currentBand.rightBodyHeight / 2 + currentBand.bottomDelta / 4
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Extra bounderies due to constrained space */
|
||||
|
||||
const upperLimit = frameTitleHeight + frameBodyHeight * 0.15;
|
||||
@@ -131,6 +129,15 @@ function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel ()
|
||||
if (bandPoint2.y < upperLimit) { bandPoint2.y = upperLimit; }
|
||||
if (bandPoint3.y < upperLimit) { bandPoint3.y = upperLimit; }
|
||||
|
||||
const leftLimit = thisObject.container.frame.width * 0.40;
|
||||
const rightLimit = thisObject.container.frame.width * 0.60;
|
||||
|
||||
if (bandPoint1.x < leftLimit) { bandPoint1.x = leftLimit; }
|
||||
if (bandPoint2.x < leftLimit) { bandPoint2.x = leftLimit; }
|
||||
|
||||
if (bandPoint3.x > rightLimit) { bandPoint3.x = rightLimit; }
|
||||
if (bandPoint4.x > rightLimit) { bandPoint4.x = rightLimit; }
|
||||
|
||||
bandPoint1 = thisObject.container.frame.frameThisPoint(bandPoint1);
|
||||
bandPoint2 = thisObject.container.frame.frameThisPoint(bandPoint2);
|
||||
bandPoint3 = thisObject.container.frame.frameThisPoint(bandPoint3);
|
||||
@@ -190,54 +197,16 @@ function newAAMastersPlottersBollingerBandsBollingerBandsBollingerBandsPanel ()
|
||||
browserCanvasContext.lineWidth = 0.2;
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
/* put the labels with the bands values */
|
||||
|
||||
|
||||
|
||||
|
||||
let y;
|
||||
|
||||
printLabel('Moving Average', X_AXIS, frameTitleHeight + frameBodyHeight * 0.05, '1');
|
||||
printLabel(currentBand.innerBand.movingAverage, X_AXIS, frameTitleHeight + frameBodyHeight * 0.10, '0.50');
|
||||
printLabel('Moving Average', X_AXIS, frameTitleHeight + frameBodyHeight * 0.05, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentBand.innerBand.movingAverage, X_AXIS, frameTitleHeight + frameBodyHeight * 0.10, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
printLabel('Deviation', X_AXIS, frameTitleHeight + frameBodyHeight * 0.95, '1');
|
||||
printLabel(currentBand.innerBand.deviation, X_AXIS, frameTitleHeight + frameBodyHeight * 0.90, '0.50');
|
||||
|
||||
function printLabel(labelToPrint, x, y, opacity) {
|
||||
|
||||
let labelPoint;
|
||||
let fontSize = 10;
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.SECONDARY + ' Saira';
|
||||
|
||||
let label = '' + labelToPrint;
|
||||
if (isNaN(label) === false) {
|
||||
label = Number(label).toLocaleString();
|
||||
}
|
||||
let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO;
|
||||
|
||||
labelPoint = {
|
||||
x: x - xOffset,
|
||||
y: y
|
||||
};
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint);
|
||||
|
||||
labelPoint = thisObject.fitFunction(labelPoint)
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')';
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y);
|
||||
|
||||
}
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
browserCanvasContext.fill();
|
||||
printLabel('Deviation', X_AXIS, frameTitleHeight + frameBodyHeight * 0.95, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentBand.innerBand.deviation, X_AXIS, frameTitleHeight + frameBodyHeight * 0.90, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersBollingerBandsPercentageBandwidth() {
|
||||
function newMastersPlottersBollingerBandsPercentageBandwidth() {
|
||||
|
||||
const MODULE_NAME = "Bands Plotter";
|
||||
const ERROR_LOG = true;
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"displayName": "Plotters Bollinger Bands",
|
||||
"codeName": "PlottersBollingerBands",
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"modules": [
|
||||
{
|
||||
"codeName": "BollingerBands",
|
||||
+78
-59
@@ -1,5 +1,5 @@
|
||||
|
||||
function newAAMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
function newMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
@@ -17,7 +17,7 @@ function newAAMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
thisObject.container.frame.containerName = "Candle";
|
||||
|
||||
let currentCandle;
|
||||
let panelTabButton
|
||||
let upDownButton
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -28,8 +28,8 @@ function newAAMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentCandle = undefined
|
||||
panelTabButton.finalize()
|
||||
panelTabButton = undefined
|
||||
upDownButton.finalize()
|
||||
upDownButton = undefined
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
@@ -40,18 +40,18 @@ function newAAMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width * 2;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.bottomLeft.y - thisObject.container.frame.height;
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
panelTabButton.fitFunction = thisObject.fitFunction
|
||||
panelTabButton.initialize()
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container;
|
||||
|
||||
container = panelTabButton.getContainer(point)
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
@@ -83,7 +83,7 @@ function newAAMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
|
||||
plotCurrentCandleInfo();
|
||||
|
||||
panelTabButton.draw()
|
||||
upDownButton.draw()
|
||||
|
||||
}
|
||||
|
||||
@@ -202,6 +202,65 @@ function newAAMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
|
||||
}
|
||||
|
||||
const leftLimit = thisObject.container.frame.width * 0.42;
|
||||
const rightLimit = thisObject.container.frame.width * 0.58;
|
||||
|
||||
if (candlePoint1.x < leftLimit) {
|
||||
|
||||
candlePoint1.x = leftLimit;
|
||||
candlePoint4.x = leftLimit;
|
||||
|
||||
}
|
||||
|
||||
if (stickPoint1.x < leftLimit) {
|
||||
|
||||
stickPoint1.x = leftLimit;
|
||||
stickPoint4.x = leftLimit;
|
||||
|
||||
}
|
||||
|
||||
if (candlePoint4.x < leftLimit) {
|
||||
|
||||
candlePoint4.x = leftLimit;
|
||||
candlePoint1.x = leftLimit;
|
||||
|
||||
}
|
||||
|
||||
if (stickPoint4.x < leftLimit) {
|
||||
|
||||
stickPoint4.x = leftLimit;
|
||||
stickPoint1.x = leftLimit;
|
||||
|
||||
}
|
||||
|
||||
if (candlePoint2.x > rightLimit) {
|
||||
|
||||
candlePoint2.x = rightLimit;
|
||||
candlePoint3.x = rightLimit;
|
||||
|
||||
}
|
||||
|
||||
if (stickPoint2.x > rightLimit) {
|
||||
|
||||
stickPoint2.x = rightLimit;
|
||||
stickPoint3.x = rightLimit;
|
||||
|
||||
}
|
||||
|
||||
if (candlePoint3.x > rightLimit) {
|
||||
|
||||
candlePoint3.x = rightLimit;
|
||||
candlePoint2.x = rightLimit;
|
||||
|
||||
}
|
||||
|
||||
if (stickPoint3.x > rightLimit) {
|
||||
|
||||
stickPoint3.x = rightLimit;
|
||||
stickPoint2.x = rightLimit;
|
||||
|
||||
}
|
||||
|
||||
|
||||
candlePoint1 = thisObject.container.frame.frameThisPoint(candlePoint1);
|
||||
candlePoint2 = thisObject.container.frame.frameThisPoint(candlePoint2);
|
||||
@@ -261,73 +320,33 @@ function newAAMastersPlottersCandlesVolumesCandlesCandlePanel() {
|
||||
browserCanvasContext.lineWidth = 1;
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
/* put the labels with the candles values */
|
||||
|
||||
|
||||
|
||||
|
||||
let y;
|
||||
|
||||
printLabel('Max', X_AXIS, frameTitleHeight + frameBodyHeight * 0.05, '1');
|
||||
printLabel(currentCandle.innerCandle.max, X_AXIS, frameTitleHeight + frameBodyHeight * 0.10, '0.50');
|
||||
|
||||
printLabel('Min', X_AXIS, frameTitleHeight + frameBodyHeight * 0.95, '1');
|
||||
printLabel(currentCandle.innerCandle.min, X_AXIS, frameTitleHeight + frameBodyHeight * 0.90, '0.50');
|
||||
printLabel('Max', X_AXIS, frameTitleHeight + frameBodyHeight * 0.05, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentCandle.innerCandle.max, X_AXIS, frameTitleHeight + frameBodyHeight * 0.10, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
printLabel('Min', X_AXIS, frameTitleHeight + frameBodyHeight * 0.95, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentCandle.innerCandle.min, X_AXIS, frameTitleHeight + frameBodyHeight * 0.90, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = Y_AXIS - currentCandle.bodyHeight / 2;
|
||||
|
||||
if (y < frameTitleHeight + frameBodyHeight * 0.15) { y = frameTitleHeight + frameBodyHeight * 0.15; }
|
||||
if (y > frameTitleHeight + frameBodyHeight * 0.80) { y = frameTitleHeight + frameBodyHeight * 0.80; }
|
||||
|
||||
printLabel('Open', X_AXIS * 1 / 2, y, '1');
|
||||
printLabel(currentCandle.innerCandle.open, X_AXIS * 1 / 2, y + frameBodyHeight * 0.05, '0.50');
|
||||
printLabel('Open', X_AXIS * 2 / 5, y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentCandle.innerCandle.open, X_AXIS * 2 / 5, y + frameBodyHeight * 0.05, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = Y_AXIS + currentCandle.bodyHeight / 2;
|
||||
|
||||
if (y < frameTitleHeight + frameBodyHeight * 0.15) { y = frameTitleHeight + frameBodyHeight * 0.15; }
|
||||
if (y > frameTitleHeight + frameBodyHeight * 0.80) { y = frameTitleHeight + frameBodyHeight * 0.80; }
|
||||
|
||||
printLabel('Close', X_AXIS * 3 / 2, y, '1');
|
||||
printLabel(currentCandle.innerCandle.close, X_AXIS * 3 / 2, y + frameBodyHeight * 0.05, '0.50');
|
||||
|
||||
|
||||
|
||||
function printLabel(labelToPrint, x, y, opacity) {
|
||||
|
||||
let labelPoint;
|
||||
let fontSize = 10;
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.SECONDARY + ' Saira';
|
||||
|
||||
let label = '' + labelToPrint;
|
||||
if (isNaN(label) === false) {
|
||||
label = Number(label).toLocaleString();
|
||||
}
|
||||
let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO;
|
||||
|
||||
labelPoint = {
|
||||
x: x - xOffset,
|
||||
y: y
|
||||
};
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint);
|
||||
labelPoint = thisObject.fitFunction(labelPoint)
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')';
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y);
|
||||
|
||||
}
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
browserCanvasContext.fill();
|
||||
printLabel('Close', X_AXIS * 7 / 5, y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentCandle.innerCandle.close, X_AXIS * 7 / 5, y + frameBodyHeight * 0.05, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersCandlesVolumesCandles() {
|
||||
function newMastersPlottersCandlesVolumesCandles() {
|
||||
|
||||
const MODULE_NAME = "Candles Plotter";
|
||||
const ERROR_LOG = true;
|
||||
@@ -263,7 +263,7 @@
|
||||
|
||||
thisObject.container.frame.draw();
|
||||
|
||||
plotChart();
|
||||
return plotChart();
|
||||
|
||||
} catch (err) {
|
||||
|
||||
@@ -469,7 +469,7 @@
|
||||
function plotChart() {
|
||||
|
||||
try {
|
||||
|
||||
let elementsPlotted = 0
|
||||
let lowResolution = false
|
||||
if (canvas.chartingSpace.viewport.zoomTargetLevel < ZOOM_OUT_THRESHOLD_FOR_PLOTTING_IN_LOW_RESOLUTION) {
|
||||
if (candles.length > 100) {
|
||||
@@ -602,6 +602,9 @@
|
||||
|
||||
candle = candles[i];
|
||||
|
||||
/* Skip the first candle with zero at open */
|
||||
if (candle.open === 0) { continue }
|
||||
|
||||
if (candle.candlePoint2.x < canvas.chartingSpace.viewport.visibleArea.bottomLeft.x || candle.candlePoint1.x > canvas.chartingSpace.viewport.visibleArea.bottomRight.x) {
|
||||
continue
|
||||
}
|
||||
@@ -691,8 +694,10 @@
|
||||
browserCanvasContext.lineTo(candle.candlePoint3.x, candle.candlePoint3.y);
|
||||
browserCanvasContext.lineTo(candle.candlePoint4.x, candle.candlePoint4.y);
|
||||
browserCanvasContext.lineTo(candle.candlePoint1.x, candle.candlePoint1.y);
|
||||
}
|
||||
|
||||
elementsPlotted++
|
||||
}
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
if (lowResolution === false) {
|
||||
@@ -746,7 +751,7 @@
|
||||
thisObject.container.eventHandler.raiseEvent("Current Record Changed", currentCandle);
|
||||
}
|
||||
}
|
||||
|
||||
return elementsPlotted
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err.stack); }
|
||||
+51
-49
@@ -1,5 +1,5 @@
|
||||
|
||||
function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
function newMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
@@ -17,7 +17,7 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
thisObject.container.frame.containerName = "Volume";
|
||||
|
||||
let currentVolume;
|
||||
let panelTabButton
|
||||
let upDownButton
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -28,8 +28,8 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentVolume = undefined
|
||||
panelTabButton.finalize()
|
||||
panelTabButton = undefined
|
||||
upDownButton.finalize()
|
||||
upDownButton = undefined
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
@@ -40,18 +40,18 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.bottomLeft.y - thisObject.container.frame.height;
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
panelTabButton.fitFunction = thisObject.fitFunction
|
||||
panelTabButton.initialize()
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container;
|
||||
|
||||
container = panelTabButton.getContainer(point)
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
@@ -83,7 +83,7 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
|
||||
plotCurrentVolumeInfo();
|
||||
|
||||
panelTabButton.draw()
|
||||
upDownButton.draw()
|
||||
}
|
||||
|
||||
function plotCurrentVolumeInfo() {
|
||||
@@ -118,6 +118,28 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
y: Y_AXIS_BUY
|
||||
};
|
||||
|
||||
/* Extra bounderies due to constrained space */
|
||||
|
||||
const upperLimit = frameTitleHeight + frameBodyHeight * 0.15;
|
||||
const downLimit = frameTitleHeight + frameBodyHeight * 0.85;
|
||||
|
||||
const leftLimit = thisObject.container.frame.width * 0.40;
|
||||
const rightLimit = thisObject.container.frame.width * 0.60;
|
||||
|
||||
if (buyVolumePoint1.y < downLimit) { buyVolumePoint1.y = downLimit; }
|
||||
if (buyVolumePoint4.y < downLimit) { buyVolumePoint4.y = downLimit; }
|
||||
|
||||
if (buyVolumePoint2.y < upperLimit) { buyVolumePoint2.y = upperLimit; }
|
||||
if (buyVolumePoint3.y < upperLimit) { buyVolumePoint3.y = upperLimit; }
|
||||
|
||||
if (buyVolumePoint1.x < leftLimit) { buyVolumePoint1.x = leftLimit; }
|
||||
if (buyVolumePoint2.x < leftLimit) { buyVolumePoint2.x = leftLimit; }
|
||||
|
||||
if (buyVolumePoint3.x > rightLimit) { buyVolumePoint3.x = rightLimit; }
|
||||
if (buyVolumePoint4.x > rightLimit) { buyVolumePoint4.x = rightLimit; }
|
||||
|
||||
|
||||
|
||||
buyVolumePoint1 = thisObject.container.frame.fitIntoFrame(buyVolumePoint1);
|
||||
buyVolumePoint2 = thisObject.container.frame.fitIntoFrame(buyVolumePoint2);
|
||||
buyVolumePoint3 = thisObject.container.frame.fitIntoFrame(buyVolumePoint3);
|
||||
@@ -153,6 +175,18 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
y: Y_AXIS_SELL
|
||||
};
|
||||
|
||||
if (sellVolumePoint1.y < upperLimit) { sellVolumePoint1.y = upperLimit; }
|
||||
if (sellVolumePoint4.y < upperLimit) { sellVolumePoint4.y = upperLimit; }
|
||||
|
||||
if (sellVolumePoint2.y > downLimit) { sellVolumePoint2.y = downLimit; }
|
||||
if (sellVolumePoint3.y > downLimit) { sellVolumePoint3.y = downLimit; }
|
||||
|
||||
if (sellVolumePoint1.x < leftLimit) { sellVolumePoint1.x = leftLimit; }
|
||||
if (sellVolumePoint2.x < leftLimit) { sellVolumePoint2.x = leftLimit; }
|
||||
|
||||
if (sellVolumePoint3.x > rightLimit) { sellVolumePoint3.x = rightLimit; }
|
||||
if (sellVolumePoint4.x > rightLimit) { sellVolumePoint4.x = rightLimit; }
|
||||
|
||||
sellVolumePoint1 = thisObject.container.frame.fitIntoFrame(sellVolumePoint1);
|
||||
sellVolumePoint2 = thisObject.container.frame.fitIntoFrame(sellVolumePoint2);
|
||||
sellVolumePoint3 = thisObject.container.frame.fitIntoFrame(sellVolumePoint3);
|
||||
@@ -168,6 +202,8 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
sellVolumePoint3 = thisObject.fitFunction(sellVolumePoint3)
|
||||
sellVolumePoint4 = thisObject.fitFunction(sellVolumePoint4)
|
||||
|
||||
|
||||
|
||||
const OPACITY = '0.40';
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
@@ -205,47 +241,13 @@ function newAAMastersPlottersCandlesVolumesVolumesVolumePanel() {
|
||||
browserCanvasContext.lineWidth = 1;
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
|
||||
/* put the labels with the volumes values */
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
printLabel('Buy Volume', X_AXIS, frameTitleHeight + frameBodyHeight * 0.95, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentVolume.innerVolumeBar.amountBuy, X_AXIS, frameTitleHeight + frameBodyHeight * 0.90, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
printLabel('Buy Volume', X_AXIS, frameTitleHeight + frameBodyHeight * 0.95, '1');
|
||||
printLabel(currentVolume.innerVolumeBar.amountBuy, X_AXIS, frameTitleHeight + frameBodyHeight * 0.90, '0.50');
|
||||
|
||||
printLabel('Sell Volume', X_AXIS, frameTitleHeight + frameBodyHeight * 0.05, '1');
|
||||
printLabel(currentVolume.innerVolumeBar.amountSell, X_AXIS, frameTitleHeight + frameBodyHeight * 0.10, '0.50');
|
||||
|
||||
|
||||
function printLabel(labelToPrint, x, y, opacity) {
|
||||
|
||||
let labelPoint;
|
||||
let fontSize = 10;
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.SECONDARY + ' Saira';
|
||||
|
||||
let label = '' + labelToPrint;
|
||||
if (isNaN(label) === false) {
|
||||
label = Number(label).toLocaleString();
|
||||
}
|
||||
|
||||
let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO;
|
||||
|
||||
labelPoint = {
|
||||
x: x - xOffset,
|
||||
y: y
|
||||
};
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint);
|
||||
labelPoint = thisObject.fitFunction(labelPoint)
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')';
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y);
|
||||
|
||||
}
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
browserCanvasContext.fill();
|
||||
printLabel('Sell Volume', X_AXIS, frameTitleHeight + frameBodyHeight * 0.05, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
printLabel(currentVolume.innerVolumeBar.amountSell, X_AXIS, frameTitleHeight + frameBodyHeight * 0.10, '1.00', 15, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersCandlesVolumesVolumes() {
|
||||
function newMastersPlottersCandlesVolumesVolumes() {
|
||||
|
||||
const MODULE_NAME = "Volumes Plotter";
|
||||
const ERROR_LOG = true;
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"displayName": "Plotters Candles & Volumes",
|
||||
"codeName": "PlottersCandlesVolumes",
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"modules": [
|
||||
{
|
||||
"codeName": "Candles",
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
function newAAMastersPlottersStairsPatternsCandleStairs() {
|
||||
function newMastersPlottersStairsPatternsCandleStairs() {
|
||||
|
||||
const MODULE_NAME = "AAMasters Plotters Stairs Patterns Candle Stairs";
|
||||
const MODULE_NAME = "Masters Plotters Stairs Patterns Candle Stairs";
|
||||
const ERROR_LOG = true;
|
||||
const INTENSIVE_LOG = false;
|
||||
const logger = newWebDebugLog();
|
||||
@@ -517,7 +517,7 @@
|
||||
let stairsPoint3;
|
||||
let stairsPoint4;
|
||||
|
||||
if (stairs.direction === 'up') {
|
||||
if (stairs.direction === 'Up') {
|
||||
|
||||
stairsPoint1 = {
|
||||
x: stairs.begin + timeFrame / 7 * 5.5,
|
||||
@@ -603,11 +603,11 @@
|
||||
|
||||
let opacity = '0.25';
|
||||
|
||||
if (stairs.direction === 'up') { browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')'; }
|
||||
if (stairs.direction === 'down') { browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + opacity + ')'; }
|
||||
if (stairs.direction === 'Up') { browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')'; }
|
||||
if (stairs.direction === 'Down') { browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + opacity + ')'; }
|
||||
|
||||
if (stairs.direction === 'up') { browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + opacity + ')'; }
|
||||
if (stairs.direction === 'down') { browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')'; }
|
||||
if (stairs.direction === 'Up') { browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + opacity + ')'; }
|
||||
if (stairs.direction === 'Down') { browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')'; }
|
||||
|
||||
if (userPositionDate >= stairs.begin && userPositionDate <= stairs.end) {
|
||||
/* highlight the current stairs */
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
function newAAMastersPlottersStairsPatternsVolumeStairs() {
|
||||
function newMastersPlottersStairsPatternsVolumeStairs() {
|
||||
|
||||
const MODULE_NAME = "AAMasters Plotters Stairs Patterns Volume Stairs";
|
||||
const MODULE_NAME = "Masters Plotters Stairs Patterns Volume Stairs";
|
||||
const ERROR_LOG = true;
|
||||
const INTENSIVE_LOG = false;
|
||||
const logger = newWebDebugLog();
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"displayName": "Plotters Stairs Patterns",
|
||||
"codeName": "PlottersStairsPatterns",
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"modules": [
|
||||
{
|
||||
"codeName": "CandleStairs",
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersTradingSimulationConditions() {
|
||||
function newMastersPlottersTradingSimulationConditions() {
|
||||
|
||||
const MODULE_NAME = "Conditions Plotter";
|
||||
const INFO_LOG = false;
|
||||
File renamed without changes.
File renamed without changes.
+1
-1
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersTradingSimulationSimulationExecution() {
|
||||
function newMastersPlottersTradingSimulationSimulationExecution() {
|
||||
|
||||
const MODULE_NAME = "Simulation Execution Plotter";
|
||||
const INTENSIVE_LOG = false;
|
||||
+11
-11
@@ -1,5 +1,5 @@
|
||||
|
||||
function newAAMastersPlottersTradingSimulationSimulationExecutionSimulationExecutionPanel() {
|
||||
function newMastersPlottersTradingSimulationSimulationExecutionSimulationExecutionPanel() {
|
||||
|
||||
|
||||
let thisObject = {
|
||||
@@ -20,7 +20,7 @@ function newAAMastersPlottersTradingSimulationSimulationExecutionSimulationExecu
|
||||
container.frame.containerName = "Trading Execution";
|
||||
|
||||
let currentRecord;
|
||||
let panelTabButton
|
||||
let upDownButton
|
||||
|
||||
return thisObject;
|
||||
|
||||
@@ -31,8 +31,8 @@ function newAAMastersPlottersTradingSimulationSimulationExecutionSimulationExecu
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentRecord = undefined
|
||||
panelTabButton.finalize()
|
||||
panelTabButton = undefined
|
||||
upDownButton.finalize()
|
||||
upDownButton = undefined
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
@@ -43,18 +43,18 @@ function newAAMastersPlottersTradingSimulationSimulationExecutionSimulationExecu
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topLeft.x + thisObject.container.frame.width * 4;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.topRight.y;
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
panelTabButton.fitFunction = thisObject.fitFunction
|
||||
panelTabButton.initialize()
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container;
|
||||
|
||||
container = panelTabButton.getContainer(point)
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
@@ -86,7 +86,7 @@ function newAAMastersPlottersTradingSimulationSimulationExecutionSimulationExecu
|
||||
|
||||
plot();
|
||||
|
||||
panelTabButton.draw()
|
||||
upDownButton.draw()
|
||||
|
||||
}
|
||||
|
||||
+28
-14
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersTradingSimulationStrategies() {
|
||||
function newMastersPlottersTradingSimulationStrategies() {
|
||||
|
||||
const MODULE_NAME = "Strategies Plotter";
|
||||
const INFO_LOG = false;
|
||||
@@ -542,26 +542,40 @@
|
||||
let imageToDraw = strategyImages[record.number];
|
||||
|
||||
|
||||
/* Draw the line that represents the duration of closed strategy */
|
||||
/* Draw the line that represents the duration of closed strategy */
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(recordPoint3.x + imageSize / 2, recordPoint3.y);
|
||||
browserCanvasContext.lineTo(recordPoint4.x - imageSize / 2, recordPoint4.y);
|
||||
browserCanvasContext.moveTo(recordPoint3.x + imageSize / 2, recordPoint3.y);
|
||||
browserCanvasContext.lineTo(recordPoint4.x - imageSize / 2, recordPoint4.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.MANGANESE_PURPLE + ', 1)';
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.MANGANESE_PURPLE + ', 1)';
|
||||
browserCanvasContext.lineWidth = 1
|
||||
|
||||
if (record.status === 1) {
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
} else {
|
||||
browserCanvasContext.setLineDash([2, 4])
|
||||
}
|
||||
browserCanvasContext.stroke()
|
||||
if (record.status === 1) {
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
} else {
|
||||
browserCanvasContext.setLineDash([2, 4])
|
||||
}
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
/* Draw the Area */
|
||||
/*
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(recordPoint1.x, recordPoint2.y);
|
||||
browserCanvasContext.lineTo(recordPoint3.x, recordPoint3.y);
|
||||
browserCanvasContext.lineTo(recordPoint4.x, recordPoint4.y);
|
||||
browserCanvasContext.lineTo(recordPoint2.x, recordPoint2.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + 0.5 + ')';
|
||||
browserCanvasContext.fill();
|
||||
*/
|
||||
/* Draw the Sticks */
|
||||
|
||||
drawStick(recordPoint1, recordPoint3);
|
||||
drawStick(recordPoint2, recordPoint4);
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersTradingSimulationTrades() {
|
||||
function newMastersPlottersTradingSimulationTrades() {
|
||||
|
||||
const MODULE_NAME = "Trades Plotter";
|
||||
const INFO_LOG = false;
|
||||
@@ -522,11 +522,11 @@
|
||||
if (record.status === 1) {
|
||||
switch (record.exitType) {
|
||||
case 1: {
|
||||
line1 = 'Exit: STOP';
|
||||
line1 = 'Stop Loss';
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
line1 = 'Exit: TP';
|
||||
line1 = 'Take Profit';
|
||||
break;
|
||||
}
|
||||
}
|
||||
+16
-6
@@ -1,4 +1,4 @@
|
||||
function newAAMastersPlottersTradingSimulationTradingSimulation() {
|
||||
function newMastersPlottersTradingSimulationTradingSimulation() {
|
||||
|
||||
const MODULE_NAME = "Simulation Plotter";
|
||||
const ERROR_LOG = true;
|
||||
@@ -384,8 +384,9 @@
|
||||
record.minimunBalanceB = dailyFile[i][31];
|
||||
record.maximunBalanceB = dailyFile[i][32];
|
||||
record.baseAsset = dailyFile[i][33];
|
||||
record.positionPeriods = dailyFile[i][34];
|
||||
record.positionDays = dailyFile[i][35];
|
||||
record.quotedAsset = dailyFile[i][34];
|
||||
record.positionPeriods = dailyFile[i][35];
|
||||
record.positionDays = dailyFile[i][36];
|
||||
|
||||
if (
|
||||
(record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) &&
|
||||
@@ -475,8 +476,9 @@
|
||||
record.minimunBalanceB = marketFile[i][31];
|
||||
record.maximunBalanceB = marketFile[i][32];
|
||||
record.baseAsset = marketFile[i][33];
|
||||
record.positionPeriods = marketFile[i][34];
|
||||
record.positionDays = marketFile[i][35];
|
||||
record.quotedAsset = marketFile[i][34];
|
||||
record.positionPeriods = marketFile[i][35];
|
||||
record.positionDays = marketFile[i][36];
|
||||
|
||||
if (
|
||||
(record.begin >= leftDate.valueOf() && record.end <= rightDate.valueOf()) &&
|
||||
@@ -514,6 +516,14 @@
|
||||
|
||||
record = records[i];
|
||||
|
||||
/* Contributing to Auto-Scale*/
|
||||
if (record.stopLoss !== 0) {
|
||||
coordinateSystem.reportYValue(record.stopLoss)
|
||||
}
|
||||
if (record.takeProfit !== 0) {
|
||||
coordinateSystem.reportYValue(record.takeProfit)
|
||||
}
|
||||
|
||||
/* Send the current record to the panel */
|
||||
|
||||
if (userPositionDate >= record.begin && userPositionDate <= record.end) {
|
||||
@@ -679,7 +689,7 @@
|
||||
browserCanvasContext.save();
|
||||
browserCanvasContext.translate(recordPoint3.x + labelOffset.x, recordPoint3.y + labelOffset.y);
|
||||
browserCanvasContext.rotate(-Math.PI / 2);
|
||||
printLabel(recordLabel, 0, 0, '1', 8);
|
||||
printLabel(recordLabel, 0, 0, '1', 8, undefined, undefined, undefined, undefined, true);
|
||||
browserCanvasContext.restore();
|
||||
}
|
||||
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
|
||||
function newMastersPlottersTradingSimulationTradingSimulationTradingSimulationAssetBalancesPanel() {
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
onRecordChange: onRecordChange,
|
||||
container: undefined,
|
||||
session: undefined,
|
||||
isVisible: true,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
};
|
||||
|
||||
let container = newContainer();
|
||||
container.initialize();
|
||||
thisObject.container = container;
|
||||
|
||||
container.frame.containerName = "Simulation Asset Balances Panel";
|
||||
|
||||
let currentRecord;
|
||||
let lastRecord;
|
||||
let upDownButton
|
||||
|
||||
const HEIGHT_FACTOR = 1.25
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize() {
|
||||
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL * 1;
|
||||
thisObject.container.frame.height = UI_PANEL.HEIGHT.NORMAL * HEIGHT_FACTOR;
|
||||
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width * 1;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.topRight.y;
|
||||
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
|
||||
thisObject.assetBalances = newAssetalances()
|
||||
thisObject.assetBalances.container.connectToParent(thisObject.container, true, true)
|
||||
thisObject.assetBalances.initialize()
|
||||
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
thisObject.session = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.onRecordChange = undefined
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentRecord = undefined
|
||||
lastRecord = undefined
|
||||
upDownButton = undefined
|
||||
|
||||
thisObject.assetBalances.finalize()
|
||||
thisObject.assetBalances = undefined
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container;
|
||||
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
|
||||
let checkPoint = {
|
||||
x: point.x,
|
||||
y: point.y
|
||||
}
|
||||
|
||||
checkPoint = thisObject.fitFunction(checkPoint)
|
||||
|
||||
if (point.x === checkPoint.x && point.y === checkPoint.y) {
|
||||
return thisObject.container;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onRecordChange(records) {
|
||||
|
||||
currentRecord = records.currentRecord;
|
||||
lastRecord = records.lastRecord
|
||||
|
||||
}
|
||||
|
||||
|
||||
function draw() {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
thisObject.container.frame.draw(false, false, true, thisObject.fitFunction);
|
||||
|
||||
plotCurrentRecordInfo();
|
||||
|
||||
upDownButton.draw()
|
||||
|
||||
thisObject.assetBalances.draw()
|
||||
|
||||
/* Define panel name */
|
||||
if (thisObject.session !== undefined) {
|
||||
const MAX_LABEL_LENGTH = 25
|
||||
if (thisObject.session.name.length > MAX_LABEL_LENGTH) {
|
||||
container.frame.containerName = thisObject.session.name.substring(0, MAX_LABEL_LENGTH) + '...'
|
||||
} else {
|
||||
container.frame.containerName = thisObject.session.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function plotCurrentRecordInfo() {
|
||||
|
||||
if (currentRecord === undefined) { return; }
|
||||
|
||||
const frameBodyHeight = thisObject.container.frame.getBodyHeight();
|
||||
const frameTitleHeight = thisObject.container.frame.height - frameBodyHeight;
|
||||
|
||||
const X_AXIS = thisObject.container.frame.width / 2;
|
||||
const Y_AXIS = frameTitleHeight + frameBodyHeight / 2;
|
||||
|
||||
/* put the labels with the records values */
|
||||
|
||||
let y = 0;
|
||||
let increment = 0.024 / HEIGHT_FACTOR * 2.5;
|
||||
|
||||
y = y + increment;
|
||||
y = y + increment;
|
||||
printLabel('Asset Balances', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
/* Parameters */
|
||||
let params
|
||||
let paramsArray = []
|
||||
let positionTaken = false
|
||||
|
||||
if (currentRecord.positionSize > 0) {
|
||||
positionTaken = true
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
paramsArray.push(params)
|
||||
|
||||
thisObject.assetBalances.setParamsArray(paramsArray)
|
||||
|
||||
}
|
||||
}
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
|
||||
|
||||
|
||||
function newMastersPlottersTradingSimulationTradingSimulationTradingSimulationCurrentPositionPanel() {
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
onRecordChange: onRecordChange,
|
||||
container: undefined,
|
||||
session: undefined,
|
||||
isVisible: true,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
};
|
||||
|
||||
let container = newContainer();
|
||||
container.initialize();
|
||||
thisObject.container = container;
|
||||
|
||||
container.frame.containerName = "Simulation Current Position Panel";
|
||||
|
||||
let currentRecord;
|
||||
let lastRecord;
|
||||
let upDownButton
|
||||
|
||||
const HEIGHT_FACTOR = 1.25
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize() {
|
||||
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL * 1;
|
||||
thisObject.container.frame.height = UI_PANEL.HEIGHT.NORMAL * HEIGHT_FACTOR;
|
||||
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width * 1;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.topRight.y;
|
||||
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
thisObject.session = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.onRecordChange = undefined
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentRecord = undefined
|
||||
lastRecord = undefined
|
||||
upDownButton = undefined
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container;
|
||||
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
|
||||
let checkPoint = {
|
||||
x: point.x,
|
||||
y: point.y
|
||||
}
|
||||
|
||||
checkPoint = thisObject.fitFunction(checkPoint)
|
||||
|
||||
if (point.x === checkPoint.x && point.y === checkPoint.y) {
|
||||
return thisObject.container;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onRecordChange(records) {
|
||||
|
||||
currentRecord = records.currentRecord;
|
||||
lastRecord = records.lastRecord
|
||||
|
||||
}
|
||||
|
||||
|
||||
function draw() {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
thisObject.container.frame.draw(false, false, true, thisObject.fitFunction);
|
||||
|
||||
plotCurrentRecordInfo();
|
||||
|
||||
upDownButton.draw()
|
||||
|
||||
/* Define panel name */
|
||||
if (thisObject.session !== undefined) {
|
||||
const MAX_LABEL_LENGTH = 25
|
||||
if (thisObject.session.name.length > MAX_LABEL_LENGTH) {
|
||||
container.frame.containerName = thisObject.session.name.substring(0, MAX_LABEL_LENGTH) + '...'
|
||||
} else {
|
||||
container.frame.containerName = thisObject.session.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function plotCurrentRecordInfo() {
|
||||
|
||||
if (currentRecord === undefined) { return; }
|
||||
|
||||
const frameBodyHeight = thisObject.container.frame.getBodyHeight();
|
||||
const frameTitleHeight = thisObject.container.frame.height - frameBodyHeight;
|
||||
|
||||
const X_AXIS = thisObject.container.frame.width / 2;
|
||||
const Y_AXIS = frameTitleHeight + frameBodyHeight / 2;
|
||||
|
||||
|
||||
/* put the labels with the records values */
|
||||
|
||||
let y = 0;
|
||||
let increment = 0.024 / HEIGHT_FACTOR * 2.5;
|
||||
|
||||
y = y + increment;
|
||||
y = y + increment;
|
||||
printLabel('Current Position', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Size', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.positionSize, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Rate', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.sellRate, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Stop', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.stopLoss, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Take Profit', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.takeProfit, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Periods', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.positionPeriods), X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Days', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.positionDays).toFixed(2), X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
y = y + increment;
|
||||
printLabel('Latest Position', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Profit / Loss', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.lastTradeProfitLoss), X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('ROI', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.lastTradeROI).toFixed(2) + ' % ', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
}
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
|
||||
function newMastersPlottersTradingSimulationTradingSimulationTradingSimulationPartialResultsPanel() {
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
onRecordChange: onRecordChange,
|
||||
container: undefined,
|
||||
session: undefined,
|
||||
isVisible: true,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
};
|
||||
|
||||
let container = newContainer();
|
||||
container.initialize();
|
||||
thisObject.container = container;
|
||||
|
||||
container.frame.containerName = "Simulation Partial Results Panel";
|
||||
|
||||
let currentRecord;
|
||||
let lastRecord;
|
||||
let upDownButton
|
||||
|
||||
const HEIGHT_FACTOR = 1.25
|
||||
|
||||
return thisObject;
|
||||
|
||||
function initialize() {
|
||||
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL * 1;
|
||||
thisObject.container.frame.height = UI_PANEL.HEIGHT.NORMAL * HEIGHT_FACTOR;
|
||||
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width * 1;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.topRight.y;
|
||||
|
||||
upDownButton = newUpDownButton()
|
||||
upDownButton.parentContainer = thisObject.container
|
||||
upDownButton.container.frame.parentFrame = thisObject.container.frame
|
||||
upDownButton.fitFunction = thisObject.fitFunction
|
||||
upDownButton.initialize()
|
||||
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
thisObject.session = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.onRecordChange = undefined
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentRecord = undefined
|
||||
lastRecord = undefined
|
||||
upDownButton = undefined
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container;
|
||||
|
||||
container = upDownButton.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
|
||||
let checkPoint = {
|
||||
x: point.x,
|
||||
y: point.y
|
||||
}
|
||||
|
||||
checkPoint = thisObject.fitFunction(checkPoint)
|
||||
|
||||
if (point.x === checkPoint.x && point.y === checkPoint.y) {
|
||||
return thisObject.container;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onRecordChange(records) {
|
||||
|
||||
currentRecord = records.currentRecord;
|
||||
lastRecord = records.lastRecord
|
||||
|
||||
}
|
||||
|
||||
|
||||
function draw() {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
thisObject.container.frame.draw(false, false, true, thisObject.fitFunction);
|
||||
|
||||
plotCurrentRecordInfo();
|
||||
|
||||
upDownButton.draw()
|
||||
|
||||
/* Define panel name */
|
||||
if (thisObject.session !== undefined) {
|
||||
const MAX_LABEL_LENGTH = 25
|
||||
if (thisObject.session.name.length > MAX_LABEL_LENGTH) {
|
||||
container.frame.containerName = thisObject.session.name.substring(0, MAX_LABEL_LENGTH) + '...'
|
||||
} else {
|
||||
container.frame.containerName = thisObject.session.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function plotCurrentRecordInfo() {
|
||||
|
||||
if (currentRecord === undefined) { return; }
|
||||
|
||||
const frameBodyHeight = thisObject.container.frame.getBodyHeight();
|
||||
const frameTitleHeight = thisObject.container.frame.height - frameBodyHeight;
|
||||
|
||||
const X_AXIS = thisObject.container.frame.width / 2;
|
||||
const Y_AXIS = frameTitleHeight + frameBodyHeight / 2;
|
||||
|
||||
|
||||
/* put the labels with the records values */
|
||||
|
||||
let y = 0;
|
||||
let increment = 0.024 / HEIGHT_FACTOR * 2.5;
|
||||
|
||||
y = y + increment;
|
||||
y = y + increment;
|
||||
printLabel('Partial Results', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Profit / Loss', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.profit, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Trades', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.roundtrips, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Hits', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.hits, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Fails', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.fails, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Hit Ratio', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.hitRatio * 100).toFixed(2) + ' %', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('ROI', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.ROI * 100).toFixed(2) + ' %', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Periods', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.periods, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Days', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.days, X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Anualized Rate of Return', X_AXIS, frameTitleHeight + frameBodyHeight * y, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.anualizedRateOfReturn * 100).toFixed(2) + ' %', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14, undefined, true, thisObject.container, thisObject.fitFunction);
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"displayName": "Plotters Trading Simulation",
|
||||
"codeName": "PlottersTradingSimulation",
|
||||
"dataMine": "AAMasters",
|
||||
"dataMine": "Masters",
|
||||
"modules": [
|
||||
{
|
||||
"codeName": "TradingSimulation",
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,348 @@
|
||||
function newAAMastersPlottersTradingSimulationFinalResults() {
|
||||
|
||||
const MODULE_NAME = "Final Results Plotter";
|
||||
const ERROR_LOG = true;
|
||||
const INTENSIVE_LOG = false;
|
||||
const logger = newWebDebugLog();
|
||||
logger.fileName = MODULE_NAME;
|
||||
|
||||
let thisObject = {
|
||||
|
||||
// Main functions and properties.
|
||||
|
||||
initialize: initialize,
|
||||
finalize: finalize,
|
||||
container: undefined,
|
||||
getContainer: getContainer,
|
||||
setTimePeriod: setTimePeriod,
|
||||
setDatetime: setDatetime,
|
||||
draw: draw,
|
||||
recalculateScale: recalculateScale,
|
||||
currentRecord: undefined
|
||||
};
|
||||
|
||||
/* this is part of the module template */
|
||||
|
||||
let container = newContainer(); // Do not touch this 3 lines, they are just needed.
|
||||
container.initialize();
|
||||
thisObject.container = container;
|
||||
|
||||
let timeLineCoordinateSystem = newTimeLineCoordinateSystem(); // Needed to be able to plot on the timeline, otherwise not.
|
||||
|
||||
let timePeriod; // This will hold the current Time Period the user is at.
|
||||
let datetime; // This will hold the current Datetime the user is at.
|
||||
|
||||
let dataFile; // This is the current Market File being plotted.
|
||||
let fileCursor; // This is the current File Cursor being used to retrieve Daily Files.
|
||||
|
||||
let singleFile; // This object will provide the different Market Files at different Time Periods.
|
||||
|
||||
/* these are module specific variables: */
|
||||
|
||||
let records = []; // Here we keep the records to be ploted every time the Draw() function is called by the AAWebPlatform.
|
||||
|
||||
let imageStopLossPhase;
|
||||
let imageTakeProfitPhase;
|
||||
let imageRecord;
|
||||
|
||||
let zoomChangedEventSubscriptionId
|
||||
let offsetChangedEventSubscriptionId
|
||||
let filesUpdatedEventSubscriptionId
|
||||
let dragFinishedEventSubscriptionId
|
||||
let dimmensionsChangedEventSubscriptionId
|
||||
|
||||
return thisObject;
|
||||
|
||||
function finalize() {
|
||||
try {
|
||||
|
||||
/* Stop listening to the necesary events. */
|
||||
|
||||
viewPort.eventHandler.stopListening(zoomChangedEventSubscriptionId);
|
||||
viewPort.eventHandler.stopListening(offsetChangedEventSubscriptionId);
|
||||
singleFile.eventHandler.stopListening(filesUpdatedEventSubscriptionId);
|
||||
canvas.eventHandler.stopListening(dragFinishedEventSubscriptionId);
|
||||
thisObject.container.eventHandler.stopListening(dimmensionsChangedEventSubscriptionId)
|
||||
|
||||
/* icons */
|
||||
|
||||
imageStopLossPhase = undefined;
|
||||
imageTakeProfitPhase = undefined;
|
||||
imageRecord = undefined;
|
||||
|
||||
/* Destroy References */
|
||||
|
||||
singleFile = undefined;
|
||||
|
||||
datetime = undefined;
|
||||
timePeriod = undefined;
|
||||
|
||||
dataFile = undefined;
|
||||
fileCursor = undefined;
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] finalize -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
/* Store the information received. */
|
||||
|
||||
singleFile = pStorage.singleFile;
|
||||
|
||||
datetime = pDatetime;
|
||||
timePeriod = pTimePeriod;
|
||||
|
||||
dataFile = singleFile.getFile(timePeriod);
|
||||
|
||||
/* Listen to the necesary events. */
|
||||
|
||||
zoomChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent("Zoom Changed", onZoomChanged);
|
||||
offsetChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent("Offset Changed", onOffsetChanged);
|
||||
filesUpdatedEventSubscriptionId = singleFile.eventHandler.listenToEvent("Files Updated", onFilesUpdated);
|
||||
dragFinishedEventSubscriptionId = canvas.eventHandler.listenToEvent("Drag Finished", onDragFinished);
|
||||
|
||||
/* Get ready for plotting. */
|
||||
|
||||
recalculate();
|
||||
|
||||
/* Ready for when dimmension changes. */
|
||||
|
||||
dimmensionsChangedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () {
|
||||
recalculate();
|
||||
})
|
||||
|
||||
callBackFunction();
|
||||
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
let container;
|
||||
/* First we check if this point is inside this space. */
|
||||
if (this.container.frame.isThisPointHere(point) === true) {
|
||||
return this.container;
|
||||
} else {
|
||||
/* This point does not belong to this space. */
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function onFilesUpdated() {
|
||||
try {
|
||||
dataFile = singleFile.getFile(timePeriod);
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] onFilesUpdated -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function setTimePeriod(pTimePeriod) {
|
||||
try {
|
||||
if (timePeriod !== pTimePeriod) {
|
||||
timePeriod = pTimePeriod;
|
||||
dataFile = singleFile.getFile(timePeriod);
|
||||
recalculate();
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function setDatetime(pDatetime) {
|
||||
datetime = pDatetime;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
try {
|
||||
// Nothing to draw for now
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] draw -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function recalculate() {
|
||||
|
||||
try {
|
||||
|
||||
records = []
|
||||
|
||||
if (timePeriod >= _1_HOUR_IN_MILISECONDS) {
|
||||
|
||||
recalculateUsingMarketFiles();
|
||||
|
||||
} else {
|
||||
|
||||
recalculateUsingDailyFiles();
|
||||
|
||||
}
|
||||
|
||||
thisObject.container.eventHandler.raiseEvent("Records Changed", records);
|
||||
|
||||
} catch (err) {
|
||||
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function recalculate() {
|
||||
|
||||
try {
|
||||
|
||||
if (dataFile === undefined) { return; } // Initialization not complete yet.
|
||||
|
||||
records = [];
|
||||
|
||||
for (let i = 0; i < dataFile.length; i++) {
|
||||
|
||||
let record = {};
|
||||
|
||||
record.begin = dataFile[i][0];
|
||||
record.end = dataFile[i][1];
|
||||
record.type = dataFile[i][2];
|
||||
record.rate = dataFile[i][3];
|
||||
record.amount = dataFile[i][4];
|
||||
record.balanceA = dataFile[i][5];
|
||||
record.balanceB = dataFile[i][6];
|
||||
record.profit = dataFile[i][7];
|
||||
record.lastTradeProfitLoss = dataFile[i][8];
|
||||
record.stopLoss = dataFile[i][9];
|
||||
record.roundtrips = dataFile[i][10];
|
||||
record.hits = dataFile[i][11];
|
||||
record.fails = dataFile[i][12];
|
||||
record.hitRatio = dataFile[i][13];
|
||||
record.ROI = dataFile[i][14];
|
||||
record.periods = dataFile[i][15];
|
||||
record.days = dataFile[i][16];
|
||||
record.anualizedRateOfReturn = dataFile[i][17];
|
||||
record.sellRate = dataFile[i][18];
|
||||
record.lastTradeROI = dataFile[i][19];
|
||||
record.strategy = dataFile[i][20];
|
||||
record.strategyPhase = dataFile[i][21];
|
||||
record.takeProfit = dataFile[i][22];
|
||||
record.stopLossPhase = dataFile[i][23];
|
||||
record.takeProfitPhase = dataFile[i][24];
|
||||
record.positionSize = dataFile[i][26]; // 25 is the message for the executor
|
||||
record.initialBalanceA = dataFile[i][27];
|
||||
record.minimunBalanceA = dataFile[i][28];
|
||||
record.maximunBalanceA = dataFile[i][29];
|
||||
record.initialBalanceB = dataFile[i][30];
|
||||
record.minimunBalanceB = dataFile[i][31];
|
||||
record.maximunBalanceB = dataFile[i][32];
|
||||
record.baseAsset = dataFile[i][33];
|
||||
record.positionPeriods = dataFile[i][34];
|
||||
record.positionDays = dataFile[i][35];
|
||||
|
||||
thisObject.currentRecord = record;
|
||||
thisObject.container.eventHandler.raiseEvent("Current Record Changed", thisObject.currentRecord);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function recalculateScale() {
|
||||
try {
|
||||
// No scale needed
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function plotChart() {
|
||||
try {
|
||||
let userPosition = getUserPosition()
|
||||
let userPositionDate = userPosition.point.x
|
||||
|
||||
let record;
|
||||
|
||||
/* Now we calculate and plot the records */
|
||||
for (let i = 0; i < records.length; i++) { // We do not start in 0 so as to be able to read the previous record i - 1
|
||||
|
||||
record = records[i];
|
||||
|
||||
/* Send the current record to the panel */
|
||||
|
||||
if (userPositionDate >= record.begin && userPositionDate <= record.end) {
|
||||
|
||||
let eventRecords = {
|
||||
currentRecord: record,
|
||||
lastRecord: records[records.length - 1]
|
||||
};
|
||||
thisObject.container.eventHandler.raiseEvent("Current Record Changed", eventRecords);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function onZoomChanged(event) {
|
||||
try {
|
||||
recalculate();
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] onZoomChanged -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function onOffsetChanged() {
|
||||
try {
|
||||
if (Math.random() * 100 > 95) {
|
||||
recalculate()
|
||||
};
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] onOffsetChanged -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function onDragFinished() {
|
||||
try {
|
||||
recalculate();
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] onDragFinished -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+86
-50
@@ -1,12 +1,10 @@
|
||||
|
||||
function newAAMastersPlottersTradingSimulationTradingSimulationTradingSimulationPanel() {
|
||||
function newAAMastersPlottersTradingSimulationTradingSimulationFinalResultsPanel() {
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
onRecordChange: onRecordChange,
|
||||
onEventRaised: onEventRaised,
|
||||
container: undefined,
|
||||
session: undefined,
|
||||
isVisible: true,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
@@ -17,7 +15,8 @@ function newAAMastersPlottersTradingSimulationTradingSimulationTradingSimulation
|
||||
container.initialize();
|
||||
thisObject.container = container;
|
||||
|
||||
container.frame.containerName = "Simulation";
|
||||
container.displacement.containerName = "Final Results";
|
||||
container.frame.containerName = "Final Results";
|
||||
|
||||
let currentRecord;
|
||||
let lastRecord;
|
||||
@@ -28,11 +27,11 @@ function newAAMastersPlottersTradingSimulationTradingSimulationTradingSimulation
|
||||
|
||||
function initialize() {
|
||||
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL * 1;
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL * 2;
|
||||
thisObject.container.frame.height = UI_PANEL.HEIGHT.NORMAL * 2.5;
|
||||
|
||||
thisObject.container.frame.position.x = canvas.chartingSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width * 1;
|
||||
thisObject.container.frame.position.y = canvas.chartingSpace.viewport.visibleArea.topRight.y;
|
||||
thisObject.container.frame.position.x = viewPort.visibleArea.topLeft.x + thisObject.container.frame.width * 1;
|
||||
thisObject.container.frame.position.y = viewPort.visibleArea.topRight.y;
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
@@ -43,21 +42,11 @@ function newAAMastersPlottersTradingSimulationTradingSimulationTradingSimulation
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
thisObject.session = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.onRecordChange = undefined
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
currentRecord = undefined
|
||||
lastRecord = undefined
|
||||
panelTabButton = undefined
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
|
||||
let container;
|
||||
|
||||
container = panelTabButton.getContainer(point)
|
||||
@@ -79,7 +68,7 @@ function newAAMastersPlottersTradingSimulationTradingSimulationTradingSimulation
|
||||
}
|
||||
|
||||
|
||||
function onRecordChange(records) {
|
||||
function onEventRaised(records) {
|
||||
|
||||
currentRecord = records.currentRecord;
|
||||
lastRecord = records.lastRecord
|
||||
@@ -88,28 +77,19 @@ function newAAMastersPlottersTradingSimulationTradingSimulationTradingSimulation
|
||||
|
||||
|
||||
function draw() {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
|
||||
thisObject.container.frame.draw(false, false, true, thisObject.fitFunction);
|
||||
|
||||
plotCurrentRecordInfo();
|
||||
|
||||
panelTabButton.draw()
|
||||
|
||||
/* Define panel name */
|
||||
if (thisObject.session !== undefined) {
|
||||
const MAX_LABEL_LENGTH = 25
|
||||
if (thisObject.session.name.length > MAX_LABEL_LENGTH) {
|
||||
container.frame.containerName = thisObject.session.name.substring(0, MAX_LABEL_LENGTH) + '...'
|
||||
} else {
|
||||
container.frame.containerName = thisObject.session.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function plotCurrentRecordInfo() {
|
||||
|
||||
if (currentRecord === undefined) { return; }
|
||||
if (lastRecord === undefined) { return; }
|
||||
|
||||
const frameBodyHeight = thisObject.container.frame.getBodyHeight();
|
||||
const frameTitleHeight = thisObject.container.frame.height - frameBodyHeight;
|
||||
@@ -173,54 +153,110 @@ function newAAMastersPlottersTradingSimulationTradingSimulationTradingSimulation
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.lastTradeROI).toFixed(2) + ' % ', X_AXIS, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
|
||||
|
||||
let bifurcationLevel = y
|
||||
y = y + increment;
|
||||
y = y + increment;
|
||||
printLabel('Partial Results', X_AXIS , frameTitleHeight + frameBodyHeight * y, '1', 14);
|
||||
printLabel('Partial Results', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Profit / Loss', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Profit / Loss', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.profit, X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel(currentRecord.profit, X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Trades', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Trades', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.roundtrips, X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel(currentRecord.roundtrips, X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Hits', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Hits', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.hits, X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel(currentRecord.hits, X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Fails', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Fails', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.fails, X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel(currentRecord.fails, X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Hit Ratio', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Hit Ratio', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.hitRatio * 100).toFixed(2) + ' %', X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel((currentRecord.hitRatio * 100).toFixed(2) + ' %', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('ROI', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('ROI', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.ROI * 100).toFixed(2) + ' %', X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel((currentRecord.ROI * 100).toFixed(2) + ' %', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Periods', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Periods', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.periods, X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel(currentRecord.periods, X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Days', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Days', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(currentRecord.days, X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel(currentRecord.days, X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Anualized Rate of Return', X_AXIS , frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
printLabel('Anualized Rate of Return', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel((currentRecord.anualizedRateOfReturn * 100).toFixed(2) + ' %', X_AXIS , frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
printLabel((currentRecord.anualizedRateOfReturn * 100).toFixed(2) + ' %', X_AXIS - thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
|
||||
y = bifurcationLevel
|
||||
|
||||
y = y + increment;
|
||||
y = y + increment;
|
||||
printLabel('Final Results', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Profit / Loss', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(lastRecord.profit, X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Trades', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(lastRecord.roundtrips, X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Hits', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(lastRecord.hits, X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Fails', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(lastRecord.fails, X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Hit Ratio', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel((lastRecord.hitRatio * 100).toFixed(2) + ' %', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('ROI', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel((lastRecord.ROI * 100).toFixed(2) + ' %', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Periods', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(lastRecord.periods, X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Days', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel(lastRecord.days, X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
y = y + increment;
|
||||
printLabel('Anualized Rate of Return', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '0.60');
|
||||
y = y + increment;
|
||||
printLabel((lastRecord.anualizedRateOfReturn * 100).toFixed(2) + ' %', X_AXIS + thisObject.container.frame.width / 4, frameTitleHeight + frameBodyHeight * y, '1.00', 14);
|
||||
|
||||
|
||||
|
||||
function printLabel(labelToPrint, x, y, opacity, fontSize) {
|
||||
+799
@@ -0,0 +1,799 @@
|
||||
function newTradingEnginesPlottersTradingSimulationSimulationExecution() {
|
||||
|
||||
const MODULE_NAME = "Simulation Execution Plotter";
|
||||
const INTENSIVE_LOG = false;
|
||||
const ERROR_LOG = true;
|
||||
const logger = newWebDebugLog();
|
||||
logger.fileName = MODULE_NAME;
|
||||
|
||||
let thisObject = {
|
||||
|
||||
// Main functions and properties.
|
||||
|
||||
initialize: initialize,
|
||||
finalize: finalize,
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
getContainer: getContainer,
|
||||
setTimeFrame: setTimeFrame,
|
||||
setDatetime: setDatetime,
|
||||
setCoordinateSystem: setCoordinateSystem,
|
||||
draw: draw
|
||||
};
|
||||
|
||||
/* this is part of the module template */
|
||||
|
||||
let container = newContainer(); // Do not touch this 3 lines, they are just needed.
|
||||
container.initialize();
|
||||
thisObject.container = container;
|
||||
|
||||
let coordinateSystem
|
||||
|
||||
let timeFrame; // This will hold the current Time Frame the user is at.
|
||||
let datetime; // This will hold the current Datetime the user is at.
|
||||
|
||||
/* these are module specific variables: */
|
||||
|
||||
let fileSequence;
|
||||
let plotElements = []; // This is where the elements to be plotted are stored before plotting.
|
||||
let plotLines = []; // Here we store the lines of open positions.
|
||||
|
||||
let previousNotesSetKey;
|
||||
|
||||
let onMouseOverEventSuscriptionId
|
||||
let offsetChangedEventSubscriptionId
|
||||
let filesUpdatedEventSubscriptionId
|
||||
let dimmensionsChangedEventSubscriptionId
|
||||
let scaleChangedEventSubscriptionId
|
||||
|
||||
let userPositionDate
|
||||
return thisObject;
|
||||
|
||||
function finalize() {
|
||||
try {
|
||||
|
||||
/* Stop listening to the necesary events. */
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
|
||||
canvas.chartingSpace.viewport.eventHandler.stopListening(offsetChangedEventSubscriptionId);
|
||||
fileSequence.eventHandler.stopListening(filesUpdatedEventSubscriptionId);
|
||||
thisObject.container.eventHandler.stopListening(dimmensionsChangedEventSubscriptionId)
|
||||
|
||||
/* Destroyd References */
|
||||
|
||||
datetime = undefined;
|
||||
timeFrame = undefined;
|
||||
|
||||
fileSequence = undefined;
|
||||
plotElements = undefined;
|
||||
plotLines = undefined;
|
||||
|
||||
thisObject.fitFunction = undefined
|
||||
|
||||
finalizeCoordinateSystem()
|
||||
coordinateSystem = undefined
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] ' + MODULE_NAME + ' -> finalize -> err = " + err.stack.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(pStorage, pDatetime, pTimeFrame, pCoordinateSystem, callBackFunction) {
|
||||
|
||||
try {
|
||||
|
||||
datetime = pDatetime;
|
||||
timeFrame = pTimeFrame;
|
||||
coordinateSystem = pCoordinateSystem
|
||||
initializeCoordinateSystem()
|
||||
|
||||
fileSequence = pStorage.fileSequences[0];
|
||||
|
||||
recalculate();
|
||||
|
||||
filesUpdatedEventSubscriptionId = fileSequence.eventHandler.listenToEvent("Files Updated", onFilesUpdated); // Only the first sequence is supported right now.
|
||||
offsetChangedEventSubscriptionId = canvas.chartingSpace.viewport.eventHandler.listenToEvent("Position Changed", onViewportPositionChanged);
|
||||
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
|
||||
/* Ready for when dimmension changes. */
|
||||
|
||||
dimmensionsChangedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () {
|
||||
recalculate();
|
||||
})
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE);
|
||||
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] ' + MODULE_NAME + ' -> initialize -> err = " + err.stack); }
|
||||
callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeCoordinateSystem() {
|
||||
scaleChangedEventSubscriptionId = coordinateSystem.eventHandler.listenToEvent('Scale Changed', onScaleChanged)
|
||||
}
|
||||
|
||||
function finalizeCoordinateSystem() {
|
||||
coordinateSystem.eventHandler.stopListening(scaleChangedEventSubscriptionId)
|
||||
}
|
||||
|
||||
function onScaleChanged() {
|
||||
recalculate();
|
||||
}
|
||||
|
||||
function onMouseOver(event) {
|
||||
let userPosition = getDateFromPointAtBrowserCanvas(event, thisObject.container, coordinateSystem)
|
||||
userPositionDate = userPosition.valueOf()
|
||||
}
|
||||
|
||||
function getContainer(point) {
|
||||
try {
|
||||
let container;
|
||||
/* First we check if this point is inside this space. */
|
||||
if (this.container.frame.isThisPointHere(point) === true) {
|
||||
return this.container;
|
||||
} else {
|
||||
/* This point does not belong to this space. */
|
||||
return undefined;
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] ' + MODULE_NAME + ' -> initialize -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function onFilesUpdated() {
|
||||
recalculate();
|
||||
}
|
||||
|
||||
function setTimeFrame(pTimeFrame) {
|
||||
timeFrame = pTimeFrame;
|
||||
recalculate();
|
||||
}
|
||||
|
||||
function setDatetime(pDatetime) {
|
||||
datetime = pDatetime;
|
||||
}
|
||||
|
||||
function setCoordinateSystem(pCoordinateSystem) {
|
||||
finalizeCoordinateSystem()
|
||||
coordinateSystem = pCoordinateSystem
|
||||
initializeCoordinateSystem()
|
||||
}
|
||||
|
||||
function onViewportPositionChanged() {
|
||||
if (Math.random() * 100 > 95) {
|
||||
recalculate()
|
||||
}
|
||||
}
|
||||
|
||||
function recalculate() {
|
||||
try {
|
||||
if (fileSequence === undefined) { return; }
|
||||
/*
|
||||
|
||||
We are going to filter the records depending on the Time Frame. We want that for a 1 min time peroid all the records appears on screen,
|
||||
but for higher periods, we will filter out some records, so that they do not overlap ever.
|
||||
|
||||
*/
|
||||
plotElements = [];
|
||||
plotLines = [];
|
||||
|
||||
let lastSellRate;
|
||||
let lastSellDate;
|
||||
let sellExecRate;
|
||||
|
||||
let lastBuyRate;
|
||||
let lastBuyDate;
|
||||
let buyExecRate;
|
||||
|
||||
let maxSequence = fileSequence.getFilesLoaded();
|
||||
|
||||
for (let j = 0; j < maxSequence; j++) {
|
||||
|
||||
let file = fileSequence.getFile(j);
|
||||
|
||||
let history = [];
|
||||
let lines = [];
|
||||
|
||||
/* First the small balls */
|
||||
|
||||
const ONE_MIN_IN_MILISECONDS = 60 * 1000;
|
||||
let step = timeFrame / ONE_MIN_IN_MILISECONDS;
|
||||
step = 1; // For now we dont discard records depending on the zoom level.
|
||||
|
||||
let i = 0;
|
||||
let lastRecordPushed = 0;
|
||||
|
||||
for (i = 0; i < file.length; i = i + step) {
|
||||
|
||||
let newHistoryRecord = {
|
||||
|
||||
date: Math.trunc(file[i][0] / 60000) * 60000 + 30000,
|
||||
buyAvgRate: file[i][1],
|
||||
sellAvgRate: file[i][2],
|
||||
|
||||
lastSellRate: file[i][3],
|
||||
sellExecRate: file[i][4],
|
||||
lastBuyRate: file[i][5],
|
||||
buyExecRate: file[i][6],
|
||||
|
||||
marketRate: file[i][7],
|
||||
newPositions: file[i][8],
|
||||
newTrades: file[i][9],
|
||||
movedPositions: file[i][10],
|
||||
profitsAssetA: file[i][11],
|
||||
profitsAssetB: file[i][12],
|
||||
combinedProfitsA: file[i][13],
|
||||
combinedProfitsB: file[i][14],
|
||||
datetime: file[i][0]
|
||||
};
|
||||
|
||||
/* Finally we add this History Record to the Array */
|
||||
|
||||
history.push(newHistoryRecord);
|
||||
lastRecordPushed = i;
|
||||
|
||||
/* Here we build the lines. */
|
||||
|
||||
//if (timeFrame <= 1 * 60 * 1000) {
|
||||
|
||||
if (newHistoryRecord.lastSellRate > 0) {
|
||||
lastSellRate = newHistoryRecord.lastSellRate;
|
||||
lastSellDate = newHistoryRecord.date;
|
||||
}
|
||||
|
||||
if (newHistoryRecord.sellExecRate > 0) {
|
||||
let newLine = {
|
||||
type: "sell",
|
||||
x1: lastSellDate,
|
||||
y1: lastSellRate,
|
||||
x2: newHistoryRecord.date,
|
||||
y2: newHistoryRecord.sellExecRate
|
||||
};
|
||||
lines.push(newLine);
|
||||
}
|
||||
|
||||
if (newHistoryRecord.lastBuyRate > 0) {
|
||||
lastBuyRate = newHistoryRecord.lastBuyRate;
|
||||
lastBuyDate = newHistoryRecord.date;
|
||||
}
|
||||
|
||||
if (newHistoryRecord.buyExecRate > 0) {
|
||||
let newLine = {
|
||||
type: "buy",
|
||||
x1: lastBuyDate,
|
||||
y1: lastBuyRate,
|
||||
x2: newHistoryRecord.date,
|
||||
y2: newHistoryRecord.buyExecRate
|
||||
};
|
||||
lines.push(newLine);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
/* We allways want to put the last record of the file on the filterd dataset, so as to allways show the latest advance of the bot. */
|
||||
|
||||
i = file.length - 1;
|
||||
|
||||
if (lastRecordPushed !== i) {
|
||||
|
||||
let newHistoryRecord = {
|
||||
|
||||
date: Math.trunc(file[i][0] / 60000) * 60000 + 30000,
|
||||
buyAvgRate: file[i][1],
|
||||
sellAvgRate: file[i][2],
|
||||
|
||||
lastSellRate: file[i][3],
|
||||
sellExecRate: file[i][4],
|
||||
lastBuyRate: file[i][5],
|
||||
buyExecRate: file[i][6],
|
||||
|
||||
marketRate: file[i][7],
|
||||
newPositions: file[i][8],
|
||||
newTrades: file[i][9],
|
||||
movedPositions: file[i][10],
|
||||
profitsAssetA: file[i][11],
|
||||
profitsAssetB: file[i][12],
|
||||
combinedProfitsA: file[i][13],
|
||||
combinedProfitsB: file[i][14]
|
||||
};
|
||||
|
||||
history.push(newHistoryRecord);
|
||||
|
||||
}
|
||||
|
||||
|
||||
for (let i = 0; i < file.length; i++) {
|
||||
|
||||
let newHistoryRecord = {
|
||||
|
||||
date: Math.trunc(file[i][0] / 60000) * 60000 + 30000,
|
||||
buyAvgRate: file[i][1],
|
||||
sellAvgRate: file[i][2],
|
||||
|
||||
lastSellRate: file[i][3],
|
||||
sellExecRate: file[i][4],
|
||||
lastBuyRate: file[i][5],
|
||||
buyExecRate: file[i][6],
|
||||
|
||||
marketRate: file[i][7],
|
||||
newPositions: file[i][8],
|
||||
newTrades: file[i][9],
|
||||
movedPositions: file[i][10],
|
||||
profitsAssetA: file[i][11],
|
||||
profitsAssetB: file[i][12],
|
||||
combinedProfitsA: file[i][13],
|
||||
combinedProfitsB: file[i][14]
|
||||
};
|
||||
|
||||
}
|
||||
plotElements.push(history);
|
||||
plotLines.push(lines);
|
||||
}
|
||||
|
||||
thisObject.container.eventHandler.raiseEvent("History Changed", history);
|
||||
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] ' + MODULE_NAME + ' -> recalculate -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
|
||||
function draw() {
|
||||
plotChart();
|
||||
}
|
||||
|
||||
function plotChart() {
|
||||
try {
|
||||
|
||||
let currentRecord
|
||||
|
||||
let point = {
|
||||
x: 0,
|
||||
y: 0
|
||||
};
|
||||
|
||||
let history;
|
||||
|
||||
for (let j = 0; j < plotElements.length; j++) {
|
||||
|
||||
let history = plotElements[j];
|
||||
|
||||
for (let i = 0; i < history.length; i++) {
|
||||
|
||||
record = history[i];
|
||||
currentRecord = record
|
||||
|
||||
let timestamp = record.date // Math.trunc(record.date / timeFrame) * timeFrame + timeFrame / 2;
|
||||
|
||||
point = {
|
||||
x: timestamp,
|
||||
y: record.marketRate
|
||||
};
|
||||
|
||||
point = coordinateSystem.transformThisPoint(point);
|
||||
point = transformThisPoint(point, thisObject.container);
|
||||
|
||||
if (point.x < canvas.chartingSpace.viewport.visibleArea.bottomLeft.x || point.x > canvas.chartingSpace.viewport.visibleArea.bottomRight.x) { continue; }
|
||||
|
||||
point = canvas.chartingSpace.viewport.fitIntoVisibleArea(point);
|
||||
point = thisObject.fitFunction(point);
|
||||
|
||||
let isCurrentRecord = false;
|
||||
|
||||
if (userPositionDate >= record.date - 30000 && userPositionDate <= record.date + 30000 - 1) {
|
||||
isCurrentRecord = true;
|
||||
}
|
||||
|
||||
let opacity = '1';
|
||||
let currentRadius = 10
|
||||
|
||||
/* Draw a red inverted triangle on exec sell */
|
||||
if (record.sellExecRate > 0) {
|
||||
|
||||
opacity = '1';
|
||||
|
||||
let normalSize = 5
|
||||
let extraSize = 0
|
||||
if (isCurrentRecord) { extraSize = 5 }
|
||||
|
||||
let point1 = {
|
||||
x: record.date,
|
||||
y: record.sellExecRate
|
||||
};
|
||||
|
||||
let point2 = {
|
||||
x: record.date + timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.sellExecRate
|
||||
};
|
||||
|
||||
let point3 = {
|
||||
x: record.date - timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.sellExecRate
|
||||
};
|
||||
|
||||
point1 = coordinateSystem.transformThisPoint(point1);
|
||||
point1 = transformThisPoint(point1, thisObject.container);
|
||||
point1 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point1);
|
||||
point1 = thisObject.fitFunction(point1);
|
||||
|
||||
point2 = coordinateSystem.transformThisPoint(point2);
|
||||
point2 = transformThisPoint(point2, thisObject.container);
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
|
||||
point3 = coordinateSystem.transformThisPoint(point3);
|
||||
point3 = transformThisPoint(point3, thisObject.container);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
let diff = point2.x - point3.x;
|
||||
point2.y = point2.y - diff;
|
||||
point3.y = point3.y - diff;
|
||||
|
||||
currentRecord.timeFrame = diff
|
||||
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(point1.x, point1.y);
|
||||
browserCanvasContext.lineTo(point2.x, point2.y);
|
||||
browserCanvasContext.lineTo(point3.x, point3.y);
|
||||
browserCanvasContext.lineTo(point1.x, point1.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')';
|
||||
|
||||
if (isCurrentRecord === false) {
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + opacity + ')';
|
||||
} else {
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + opacity + ')'; /* highlight the current record */
|
||||
}
|
||||
|
||||
browserCanvasContext.fill();
|
||||
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 0.25;
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
}
|
||||
|
||||
/* Draw a green triangle on exec buy */
|
||||
if (record.buyExecRate > 0) {
|
||||
|
||||
opacity = '1';
|
||||
|
||||
let normalSize = 5
|
||||
let extraSize = 0
|
||||
if (isCurrentRecord) { extraSize = 5 }
|
||||
|
||||
let point1 = {
|
||||
x: record.date,
|
||||
y: record.buyExecRate
|
||||
};
|
||||
|
||||
let point2 = {
|
||||
x: record.date + timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.buyExecRate
|
||||
};
|
||||
|
||||
let point3 = {
|
||||
x: record.date - timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.buyExecRate
|
||||
};
|
||||
|
||||
point1 = coordinateSystem.transformThisPoint(point1);
|
||||
point1 = transformThisPoint(point1, thisObject.container);
|
||||
point1 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point1);
|
||||
point1 = thisObject.fitFunction(point1);
|
||||
|
||||
point2 = coordinateSystem.transformThisPoint(point2);
|
||||
point2 = transformThisPoint(point2, thisObject.container);
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
|
||||
point3 = coordinateSystem.transformThisPoint(point3);
|
||||
point3 = transformThisPoint(point3, thisObject.container);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
let diff = point2.x - point3.x;
|
||||
point2.y = point2.y + diff;
|
||||
point3.y = point3.y + diff;
|
||||
|
||||
currentRecord.timeFrame = diff
|
||||
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(point1.x, point1.y);
|
||||
browserCanvasContext.lineTo(point2.x, point2.y);
|
||||
browserCanvasContext.lineTo(point3.x, point3.y);
|
||||
browserCanvasContext.lineTo(point1.x, point1.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + opacity + ')';
|
||||
|
||||
if (isCurrentRecord === false) {
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')';
|
||||
} else {
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + opacity + ')'; /* highlight the current record */
|
||||
}
|
||||
|
||||
browserCanvasContext.fill();
|
||||
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 0.25;
|
||||
browserCanvasContext.stroke();
|
||||
}
|
||||
|
||||
/* Draw a red inverted triangle on sell */
|
||||
if (record.lastSellRate > 0) {
|
||||
opacity = '1';
|
||||
|
||||
let normalSize = 5
|
||||
let extraSize = 0
|
||||
if (isCurrentRecord) { extraSize = 5 }
|
||||
|
||||
let point1 = {
|
||||
x: record.date,
|
||||
y: record.lastSellRate
|
||||
};
|
||||
|
||||
let point2 = {
|
||||
x: record.date + timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.lastSellRate
|
||||
};
|
||||
|
||||
let point3 = {
|
||||
x: record.date - timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.lastSellRate
|
||||
};
|
||||
|
||||
point1 = coordinateSystem.transformThisPoint(point1);
|
||||
point1 = transformThisPoint(point1, thisObject.container);
|
||||
point1 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point1);
|
||||
point1 = thisObject.fitFunction(point1);
|
||||
|
||||
point2 = coordinateSystem.transformThisPoint(point2);
|
||||
point2 = transformThisPoint(point2, thisObject.container);
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
|
||||
point3 = coordinateSystem.transformThisPoint(point3);
|
||||
point3 = transformThisPoint(point3, thisObject.container);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
let diff = point2.x - point3.x;
|
||||
point2.y = point2.y - diff;
|
||||
point3.y = point3.y - diff;
|
||||
|
||||
currentRecord.timeFrame = diff
|
||||
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(point1.x, point1.y);
|
||||
browserCanvasContext.lineTo(point2.x, point2.y);
|
||||
browserCanvasContext.lineTo(point3.x, point3.y);
|
||||
browserCanvasContext.lineTo(point1.x, point1.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
if (isCurrentRecord === false) {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + opacity + ')';
|
||||
} else {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + opacity + ')'; /* highlight the current record */
|
||||
}
|
||||
|
||||
browserCanvasContext.fill();
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + opacity + ')';
|
||||
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 0.25;
|
||||
browserCanvasContext.stroke();
|
||||
}
|
||||
|
||||
/* Draw a green triangle on buy */
|
||||
if (record.lastBuyRate > 0) {
|
||||
|
||||
opacity = '1';
|
||||
|
||||
let normalSize = 5
|
||||
let extraSize = 0
|
||||
if (isCurrentRecord) { extraSize = 5 }
|
||||
|
||||
let point1 = {
|
||||
x: record.date,
|
||||
y: record.lastBuyRate
|
||||
};
|
||||
|
||||
let point2 = {
|
||||
x: record.date + timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.lastBuyRate
|
||||
};
|
||||
|
||||
let point3 = {
|
||||
x: record.date - timeFrame / 7 * (normalSize + extraSize),
|
||||
y: record.lastBuyRate
|
||||
};
|
||||
|
||||
point1 = coordinateSystem.transformThisPoint(point1);
|
||||
point1 = transformThisPoint(point1, thisObject.container);
|
||||
point1 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point1);
|
||||
point1 = thisObject.fitFunction(point1);
|
||||
|
||||
point2 = coordinateSystem.transformThisPoint(point2);
|
||||
point2 = transformThisPoint(point2, thisObject.container);
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
|
||||
point3 = coordinateSystem.transformThisPoint(point3);
|
||||
point3 = transformThisPoint(point3, thisObject.container);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
let diff = point2.x - point3.x;
|
||||
point2.y = point2.y + diff;
|
||||
point3.y = point3.y + diff;
|
||||
|
||||
currentRecord.timeFrame = diff
|
||||
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point3 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point3);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
point3 = thisObject.fitFunction(point3);
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(point1.x, point1.y);
|
||||
browserCanvasContext.lineTo(point2.x, point2.y);
|
||||
browserCanvasContext.lineTo(point3.x, point3.y);
|
||||
browserCanvasContext.lineTo(point1.x, point1.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
if (isCurrentRecord === false) {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + opacity + ')';
|
||||
} else {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + opacity + ')'; /* highlight the current record */
|
||||
}
|
||||
|
||||
browserCanvasContext.fill();
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')';
|
||||
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 0.25;
|
||||
browserCanvasContext.stroke();
|
||||
}
|
||||
|
||||
/* Send the current record to the panel */
|
||||
|
||||
if (userPositionDate >= record.date - 30000 && userPositionDate < record.date + 30000) {
|
||||
thisObject.container.eventHandler.raiseEvent("Current Record Changed", currentRecord);
|
||||
}
|
||||
|
||||
/* Circles */
|
||||
|
||||
let radius = 2;
|
||||
currentRadius = 10
|
||||
|
||||
/* Outer Circle */
|
||||
|
||||
if (isCurrentRecord === true) {
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')';
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + opacity + ')'; /* highlight the current record */
|
||||
|
||||
browserCanvasContext.arc(point.x, point.y, currentRadius, 0, Math.PI * 2, true);
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
if (point.x < canvas.chartingSpace.viewport.visibleArea.topLeft.x + 50 || point.x > canvas.chartingSpace.viewport.visibleArea.bottomRight.x - 50) {/*we leave this history without fill. */ } else {
|
||||
browserCanvasContext.fill();
|
||||
}
|
||||
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 0.25;
|
||||
browserCanvasContext.stroke();
|
||||
}
|
||||
|
||||
/* Inner Circle */
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')';
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + opacity + ')';
|
||||
|
||||
browserCanvasContext.arc(point.x, point.y, radius, 0, Math.PI * 2, true);
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
if (point.x < canvas.chartingSpace.viewport.visibleArea.topLeft.x + 50 || point.x > canvas.chartingSpace.viewport.visibleArea.bottomRight.x - 50) {/*we leave this history without fill. */ } else {
|
||||
browserCanvasContext.fill();
|
||||
}
|
||||
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 0.25;
|
||||
browserCanvasContext.stroke();
|
||||
|
||||
}
|
||||
|
||||
/* Draw the lines connecting plot elements. */
|
||||
let lines = plotLines[j];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
|
||||
let line = lines[i];
|
||||
|
||||
opacity = '1';
|
||||
|
||||
let point1 = {
|
||||
x: line.x1,
|
||||
y: line.y1
|
||||
};
|
||||
|
||||
let point2 = {
|
||||
x: line.x2,
|
||||
y: line.y2
|
||||
};
|
||||
|
||||
point1 = coordinateSystem.transformThisPoint(point1);
|
||||
point1 = transformThisPoint(point1, thisObject.container);
|
||||
point1 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point1);
|
||||
point1 = thisObject.fitFunction(point1);
|
||||
|
||||
point2 = coordinateSystem.transformThisPoint(point2);
|
||||
point2 = transformThisPoint(point2, thisObject.container);
|
||||
point2 = canvas.chartingSpace.viewport.fitIntoVisibleArea(point2);
|
||||
point2 = thisObject.fitFunction(point2);
|
||||
|
||||
browserCanvasContext.beginPath();
|
||||
|
||||
browserCanvasContext.moveTo(point1.x, point1.y);
|
||||
browserCanvasContext.lineTo(point2.x, point2.y);
|
||||
|
||||
browserCanvasContext.closePath();
|
||||
|
||||
if (line.type === "sell") {
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + opacity + ')';
|
||||
} else {
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')';
|
||||
}
|
||||
|
||||
browserCanvasContext.setLineDash([4, 1])
|
||||
browserCanvasContext.lineWidth = 0.25;
|
||||
browserCanvasContext.stroke();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write("[ERROR] ' + MODULE_NAME + ' -> plotChart -> err = " + err.stack); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loaded 100 of 2055 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user